LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Error calling DLL in LabVIEW, but works in VC

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. 

Test_C.jpg

 

And this is the VI that does not work. 

LV_Call.jpg

 

In the attached files, 'libcontour.zip' contains the matlab-generated dll and wrapper dll. 

Download All
0 Kudos
Message 1 of 12
(4,622 Views)

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)

0 Kudos
Message 2 of 12
(4,609 Views)

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.

0 Kudos
Message 3 of 12
(4,604 Views)

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;

0 Kudos
Message 4 of 12
(4,596 Views)

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.

0 Kudos
Message 5 of 12
(4,591 Views)

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.

Message 6 of 12
(4,582 Views)

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.

0 Kudos
Message 7 of 12
(4,580 Views)

Good catch 

0 Kudos
Message 8 of 12
(4,574 Views)

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?

0 Kudos
Message 9 of 12
(4,557 Views)

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.

 

 

0 Kudos
Message 10 of 12
(4,554 Views)