torekp Posted April 11, 2018 Report Posted April 11, 2018 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 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. Quote
JKSH Posted April 12, 2018 Report Posted April 12, 2018 (edited) 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 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/ dimSizes contains the sizes of 2 dimensions. element is the interleaved array. Even though the header suggests its size is 1, its real size is dimSizes[0] * dimsizes[1]. (This technique is called the "C Struct Hack": see https://tonywearme.wordpress.com/2011/07/26/c-struct-hack/ or https://aticleworld.com/struct-hack-in-c/) 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 April 13, 2018 by JKSH Fix code errors Quote
torekp Posted April 12, 2018 Author Report Posted April 12, 2018 (edited) 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 April 12, 2018 by torekp Quote
JKSH Posted April 13, 2018 Report Posted April 13, 2018 (edited) 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 April 14, 2018 by JKSH 1 Quote
torekp Posted April 13, 2018 Author Report Posted April 13, 2018 Yes! Thank you, problem solved! Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.