10-18-2016 06:36 PM
I am trying to call a dll but failing. The dll call is "long Function (long myfcthandle, const MATRIX* pDataMatrix)
MATRIX is defined as structure of NumColumns, NumRows, NumPlanes, Array where the Num* values are long integers (U32) and the Array is a 3 dimensional floating point array with the Num* dimensions. NumPlanes is always 1. In my case the Array is vector so NumRows also = 1. pDataMatrix is a pointer to the Matrix data. The MATRIX array contains my data that the dll is supposed to use for its calculations. I have tried every possible combination of calls but have not gotten it to work. The error is usually 1097 indicating a memory violation. This particular call is not supposed to be allocating memory but other functions within this dll does. What is the proper method of calling this dll?
10-21-2016 08:06 AM - edited 10-21-2016 08:07 AM
You will have to show more than just an incomplete function prototype. multidimensional arrays are not defined by C at all, and how they are implemented is entirely up to the programmer. LabVIEW multidimensional arrays are in fact one single memory block with x * y * z elements, assuming x, y, z are the dimensional sizes.
If your function uses a different layout such as an array of pointers to pointers then you can NOT interface this directly with the Call Library Node. While it is theoretically possible to create an array of that type on the LabVIEW diagram to be passed to the function, this involves pretty much starting to play C compiler yourself with all the necessary nitty gritty details about how the C compiler arranges data in memory. It is much easier and more maintainable to create a wrapper DLL in C, that translates between a LabVEW friendly datatype and your C type pointers and if that is not an option because you do not know how or are not able to create such a DLL, then trying to play C compiler yourself is anyhow a hopeless adventure.
10-21-2016 08:40 AM
Memory violation has nothing to do with memory allocation. It's a windows native error code that tells you that your software tryed to access a memory address which is not accessible. It happens often when you pass pointers around that points to the wrong place. As somebody was telling you before you might want to create an adapter function that translates your matrix into something reasonable like a linear array and back.
10-21-2016 11:00 AM
Thanks for the responses. Sorry if I am a little dense. I am an old Fortran progammer and have no C experience.
As I understand it the function call is asking for a structure of four elements: (NumCol, NumRows, NumPlanes, pointer to array). The array theoretically is 3 dimensionally but in my case is n,1,1 hence only a vector. I do understand that arrays are stored in memory as a vector with the dimensions defining the break points. The 4 element structure needs to be passed by value. How do I get a pointer to my vector in LV so I can include it in the structure and pass it to the DLL?
10-24-2016 01:27 AM
This should be it
10-24-2016 02:00 AM - edited 10-24-2016 02:02 AM
Discard the above picture. This should be what the call looks like.
Also I noticed you are not passing any information about the array size to the DLL. How does the DLL know what the data size is?
10-24-2016 02:11 AM - edited 10-24-2016 02:22 AM
Unfortunately that won't work like that. From the description of the first post the definition for MATRIX is more along the lines of:
typedef struct { long NumRows; long NumCols; long NumPages; float *array; } MATRIX;
So unless you want to play C compiler and retrieve the array data pointer of the PREALLOCATED LabVIEW array to copy it into the structure there is no way to do this structure directly in the LabVIEW diagram.
Extra complication here will be that if you would do above voodoo programming, you have to make sure that the PREALLOCATED LabVIEW array stays valid until after the Call Library Node (CLN) has finished. Since there is no direct wire for this array to the Call Library Node, LabVIEW has no way of determining that this array is actually used by the code behind the Call Library Node, so unless you specifically make sure that the array stays alive until after the CLN returns (through some artificial data dependency) it may feel like deallocating (or reallocating) that array right before or during the call to the CLN, causing the DLL call in the CLN to generate a General Protection Fault Error.
And while LabVIEW currently doesn't do reallocating of data arrays if you don't do an explicit resize to the wire, this may not be true in future versions with new CPU architectures that allow some crazy and yet to be invented optimization tricks.
10-24-2016 02:39 AM
Then no other way other than writing a wrapper DLL function that translate the following (where the array is inlined in the stucture) to a structure with the pointer
typedef struct { long NumRows; long NumCols; long NumPages; float data; } MATRIX;
typedef struct { long NumRows; long NumCols; long NumPages; float *array; } MATRIX2;
MATRIX s;
MATRIX2 d;
long Function_Wrapper (long myfcthandle, const MATRIX* s)
{
d.NumRows = s.NumRows;
d.NumCols = s.NumCols;
d.NumPages = s.NumPages;
d.array = &s.data;
return Function(myfcthandle, &d);
}
10-24-2016 02:41 AM
wrapper CLN looking like this
10-24-2016 09:04 AM - edited 10-24-2016 09:09 AM
That example code is badly misleading:
The array handle passed from LabVIEW has this datatype:
#include "lv_prolog.h"
typedef struct { int32_t dim1; int32_t dim2; int32_t dim3; float elms[0]; } TD3DFloatArray. **TD3DFloatArrHdl;
#include "lv_epilog.h"
long Function_Wrapper (long myfcthandle, const TD3DFloatArrHdl arr)
{
MATRIX m;
m.NumRows = (*arr)->dim1;
m.NumCols = (*arr)->dim2;
m.NumPages = (*arrs)->dim3;
m.array = (*arr)->elms;
return Function(myfcthandle, &m);
}
Then you can directly pass the LabVIEW array into the CLN with configuration Array, Datatype: 4 byte Single, 3 dimensions, pass: Array Handle