Jump to content

LV DLL creates mysterious DoubleArray class


Recommended Posts

So I created a DLL from a Labview VI that has a 2D array input (and some scalar inputs) and some 2D array outputs.  Labview creates a .h file with these lines

DoubleArray.PNG

And then it defines the 2D array arguments to my function as being of this type: "void __cdecl Linear_discrim_4dll(DoubleArray *dataObsFeat, int32_t grpAsz," etc etc.  Trouble is, I have no idea how to fill out this structure so that the DLL can use it.  Say for simplicity I had a 2 by 3 input called dataObsFeat with elements {1,2,3; 11,12,13}; how would I create the object with these values in C or C++ and pass it to the function?  I am a total C++ noob, in case it isn't obvious.

Link to comment
On ‎11‎/‎04‎/‎2018 at 10:53 PM, torekp said:

So I created a DLL from a Labview VI that has a 2D array input (and some scalar inputs) and some 2D array outputs.  Labview creates a .h file with these lines

DoubleArray.PNG

And then it defines the 2D array arguments to my function as being of this type: "void __cdecl Linear_discrim_4dll(DoubleArray *dataObsFeat, int32_t grpAsz," etc etc.  Trouble is, I have no idea how to fill out this structure so that the DLL can use it.  Say for simplicity I had a 2 by 3 input called dataObsFeat with elements {1,2,3; 11,12,13}; how would I create the object with these values in C or C++ and pass it to the function?  I am a total C++ noob, in case it isn't obvious.

See the memory layout of Arrays at http://zone.ni.com/reference/en-XX/help/371361P-01/lvconcepts/how_labview_stores_data_in_memory/

 

If you create the 2-by-3 array in LabVIEW and pass it to your DLL, you can read it in C/C++like this:

void vi1(DoubleArray *array_fromLv)
{
    double cArray[2][3];
    cArray[0][0] = (*array_fromLv)->element[0];
    cArray[0][1] = (*array_fromLv)->element[1];
    cArray[0][2] = (*array_fromLv)->element[2];
    cArray[1][0] = (*array_fromLv)->element[3];
    cArray[1][1] = (*array_fromLv)->element[4];
    cArray[1][2] = (*array_fromLv)->element[5];

    // Do stuff...
}

 

To pass array data from the DLL to LabVIEW, the idea is to do the opposite:
void vi2(DoubleArray *array_toLv)
{
    double cArray[2][3];

    // Do stuff...

    (*array_toLv)->element)[0] = cArray[0][0];
    (*array_toLv)->element)[1] = cArray[0][1];
    (*array_toLv)->element)[2] = cArray[0][2];
    (*array_toLv)->element)[3] = cArray[1][0];
    (*array_toLv)->element)[4] = cArray[1][1];
    (*array_toLv)->element)[5] = cArray[1][2];
}

 

VERY IMPORTANT: Before your DLL writes any data, you must properly allocate the memory. There are 2 ways to do this:

  • Pre-allocate the array in LabVIEW, pass this array into the DLL, and let the DLL overwrite the array contents, OR
  • Call LabVIEW Manager functions (http://zone.ni.com/reference/en-XX/help/371361P-01/lvexcodeconcepts/labview_manager_routines/ ) to allocate or resize the array before writing the data. These functions are poorly-documented, however.
 

 

Edited by JKSH
Fix code errors
Link to comment

Thanks!  Sorry, I wasn't clear.  I'm not trying to use a DLL in Labview.  I'm trying to use a DLL (that Labview created) in C++.  I read the first website on the "C Struct Hack" and tried to apply it to your advice, yielding this:

int i;       
int len = 2, len2 = 3;
int32_t datasz[2]={2,3};
double data1d[6] = { 1,2,3,11,12,13};
double aresult[2][2];
DoubleArray dataouta;
DoubleArray datain;

void viGet(DoubleArrayBase * result)
{
    for (i=0; i<4; i++) aresult[i/2][i%2] = (result->element);
}
void viSet(DoubleArrayBase * myArray)
{
    (myArray->dimSizes)[0] = 2;
    (myArray->dimSizes)[1] = 3;
    for (i=0; i<6; i++) (myArray->element) = data1d;
}

int main(int argc, char *argv[])
{
    viSet(datain);
    Linear_discrim_4dll(&datain,&dataouta,len,len2);
    viGet(dataouta);
)

and some printf statements.  This compiles (yay, a first!) but has a Fatal Runtime Error dereferencing a null pointer to datain, at the call to viSet.

Edited by torekp
Link to comment

My apologies, I remembered wrongly and gave you wrong code. I've fixed my previous post now.

The syntax is funny because:

  • DoubleArrayBase is the struct itself.
  • DoubleArray is a pointer to a pointer to a DoubleArray struct (yes, you read that right)
On ‎12‎/‎04‎/‎2018 at 9:46 PM, torekp said:

I'm not trying to use a DLL in Labview.  I'm trying to use a DLL (that Labview created) in C++.

Everything in the first half of my previous post (up to and including the first block of code) still applies to C++ code that reads array data from the DLL.

C++ code that writes array data into LabVIEW is a bit more complex. Look in your LabVIEW-generated header file again: Do you see functions called AllocateDoubleArray() and DeAllocateDoubleArray()?

// In the LabVIEW-generated header, mydll.h
typedef struct {
	int32_t dimSizes[2];
	double element[1];
} DoubleArrayBase;
typedef DoubleArrayBase **DoubleArray;

DoubleArray __cdecl AllocateDoubleArray (int32_t *dimSizeArr);
MgErr __cdecl DeAllocateDoubleArray (DoubleArray *hdlPtr);


// In your code
#include "mydll.h"

int main()
{
	// Allocate and write the input array
	int32_t datasz[2] = {2, 3};
	DoubleArray arrayIn = AllocateDoubleArray(datasz);
	(*arrayIn)->element[0] = 1;
	(*arrayIn)->element[1] = 2;
	(*arrayIn)->element[2] = 3;
	(*arrayIn)->element[3] = 11;
	(*arrayIn)->element[4] = 12;
	(*arrayIn)->element[5] = 13;

	// Call your function
	DoubleArray arrayOut;
	Linear_discrim_4dll(&arrayIn, &arrayOut, 2, 3);

	// Extract data from the output array, ASSUMING the output is 2x2
	double cArray[2][2];
	cArray[0][0] = (*arrayOut)->element[0];
	cArray[0][1] = (*arrayOut)->element[1];
	cArray[1][0] = (*arrayOut)->element[2];
	cArray[1][1] = (*arrayOut)->element[3];

	// Free the input array's memory
	DeAllocateDoubleArray(&arrayIn);

	// ...
}

 

Edited by JKSH
  • Like 1
Link to comment

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.