07-31-2013 12:48 PM
I compiled a DLL from Matlab, and then compiled a wrapper DLL in VC++. I tested the wrapper DLL in VC++, and it works fine, generating the correct output as in Matlab.
But when I call the wrapper DLL in LabVIEW, the first thing I noticed was that it only ran once. The second time I ran the VI, it returns an error. And the output is always a single number instead of an array when it runs.
I followed the examples how to create a wrapper DLL for Matlab compiled code. One of the examples said three functions Initialize, run and terminate should be implemented so that the DLL function can run continuously. I did all those, but it still does not work.
Here is the test code in C++. I explicitely loaded the DLL and ran the functions. It worked fine. Why the VI in LabVIEW does not do the same thing?
// contourWrapper3.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <Windows.h> #include <iostream> typedef int (*InitFunc)(); typedef void (*TerminateFunc)(); typedef void (*contourFunc)(double*,double*,int,int,double); int _tmain(int argc, _TCHAR* argv[]) { InitFunc _InitFunc; TerminateFunc _TerminateFunc; contourFunc _contour; HINSTANCE hInstLibrary = LoadLibrary("contourcWrapper.dll"); if(hInstLibrary) { _InitFunc=(InitFunc)GetProcAddress(hInstLibrary,"contourcInit"); _TerminateFunc=(TerminateFunc)GetProcAddress(hInstLibrary,"contourcTerminate"); _contour=(contourFunc)GetProcAddress(hInstLibrary,"contourcGenerate"); if(_InitFunc) _InitFunc(); if(_contour) { double image2DArray[] = {1,2,6,4,6,8,0,5,1,3,5,4,7,8,8,9,10,0}; int width = 3; int height = 6; double c[sizeof image2DArray] = {0}; _contour(c, image2DArray, width, height, 0.6); for (int i=0; i<width*height; ++i) { std::cout << c[i] << std::endl; } } _TerminateFunc(); } else std::cerr << "Could not initialize libcontour properly." << std::endl; return 0; }
This is the output window of the above C tester code. It displays the correct output of array.
And this is the VI that does not work.
In the attached files, 'libcontour.zip' contains the matlab-generated dll and wrapper dll.
07-31-2013 01:18 PM
I cannot test it myself because I am still missing DLLs (likely relating MatLab) but there are obvious differences in the wrappers. (at least from what I am seeing). I admit to being rusty though.
In the VC++ code it looks like you are using 1D arrays. Simply calling a 1D array "image2DArray" does not make it so.
type name[size1][size2]...[sizeN];
2D arrays would need two sets of brackets no?
While in LabVIEW, supposedly equal code, you are using 2D arrays.
Hope this helps... (and is accurate)
07-31-2013 01:26 PM
But C++ does not differentiate 1D or multiple D array I think. They are all a pointer pointing to a string of memory locations. So a 2D will be converted to a 1D array, row-based in C.
07-31-2013 01:49 PM
But LabVIEW does. The declarations (in C) for different types of arrays are not the same. I think you are passing extranious data to the DLL which is causing the issue.
I will defer to your expertise however. Over the years my knowledge in this area has waned. Perhaps you are correct (in which case I am not sure what is wrong).
Examples:
typedef struct
{
int dimSize;
double data[1];
} t_LvArrayDbl1D, *p_LvArrayDbl1D, **h_LvArrayDbl1D;
typedef struct
{
int dimSize[2];
double data[1];
} t_LvArrayDbl2D, *p_LvArrayDbl2D, **h_LvArrayDbl2D;
07-31-2013 01:54 PM - edited 07-31-2013 01:56 PM
I believe your problem is that you are not initializing the output array contourc (or just c in your example C++ code) to a large enough array. In the C++ code, you initalize it to an array the size of image2DArray, but in LabVIEW you initialize it to a single element. Use "Initialize Array" to create an array of the correct size before you pass it to the DLL function.
EDIT: This of course also explains why the output is always a single number rather than a full array.
07-31-2013 02:08 PM
Don - the C structs that you posted apply only when passing an array to a DLL as a LabVIEW array handle, not when passing as a pointer to the array data as is being done here.
07-31-2013 02:17 PM
You are right. After I inited the array to the size of the image2DArray, it returns the entire array.
But still it only runs once. The second time I click 'Run', it returns error 1097. I have to completely shut down LabVIEW and reopen to run it again. I have a feeling it is something about the init/terminate the DLL calling stuff, but I don't really know where.
07-31-2013 02:28 PM - edited 07-31-2013 02:28 PM
Good catch nathand
After I posted I realised it did not really matter if they were different. As long as the interface, from LabVIEWs point of view, was correct the data should be the same.
Kudos from me
07-31-2013 04:23 PM
MengHuiHanTang wrote:
But still it only runs once. The second time I click 'Run', it returns error 1097. I have to completely shut down LabVIEW and reopen to run it again. I have a feeling it is something about the init/terminate the DLL calling stuff, but I don't really know where.
Without knowing anything about what's in those DLL calls, I can't help at all. Why do you think you need the initialize and terminate calls? What example did you follow?
07-31-2013 04:39 PM
It all started from this post back in 2011.
http://forums.ni.com/t5/LabVIEW/dll-matlab-an-LadVIEW/td-p/47127
Someone did it, compile the .m code, wrote a wrapper DLL in C/C++, and called it in LabVIEW. It worked, then a lot of people followed the steps, including me. Initialization is needed to involve Matlab compiler. Down to the bottom of the code is a Matlab compiled C code. That's why it is needed. Thanks for you help. Appreciate it.