LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Calling a DLL written for VB from LabVIEW

I need to call from LabVIEW 7.0 a DLL originally written for VB. The DLL exposes functions that take as arguments BSTR* and SAFEARRAY*. However, trying to call one of the functions that modifies a passed BSTR causes LabVIEW to crash.
If I run the DLL in Visual Studio (it's written in C) and set a breakpoint just within the function, I find that LabView crashes before the function is entered. If I change the function argument type from BSTR* to BSTR (and make all other required changes in the DLL, including the interface definition) I find that LabView does not crash before the function code is reached, but it does not pass a properly-formed BSTR.
Interestingly, regardless of whether the function declares its argument as BST
R or BSTR*, LabView still reports the parameter as CStr when it reads the interface definition file. (In the Configure dialog of the code interface VI).
Can anyone suggest what I need to do to pass a string correctly to the DLL?
Also, can LabVIEW handle conversion of arrays to SAFEARRAY, and how should I set it up for this?
Many thanks.
0 Kudos
Message 1 of 4
(3,766 Views)
Hi Nick,

It's Friday afternoon, and my brain is not at optimal respond condition, but I will try to help you... 🐵

Looks like the two functions are pointers. So if you are not using pointers it can be a source of your problem.

So... in Labview, you should use the "Call Library Function Node" which is located in the Functions Palette under "Advanced". Double click the Fn Node to open it and select the dll under the select Library Name or Path (browse button on the right). Within the dll, select your function, one at a time and create a (sub) vi for each of the function call. Pass values by selecting the parameter name and setting its type....

Under calling convention, you typically have a couple of choices. Select "C".

To answer your que
stion of how to pass a string, once you do the steps above, you then select Type "String" and String Format "C String Pointer" . I based this on the fact that your arguements are BSTR* and SAFEARRAY*.

By the way, if both parameters are in the same function, DO NOT create 2 functions, but rather add a parameter to this function name.

Select the return parameter, whether it is void or a value. Set it appropriately.

Try this to see if the "crash" goes away. As for the conversion of arrays, yes, LV should be able to handle that. Please provide more details of what you want to do with the array.

Regards,

JLV
Message 2 of 4
(3,766 Views)
Joe,
Many thanks for your reply. Let me give you some more detail, focussing for now on the BSTR issue. I'm calling a function GetErrorMessage that uses an HRESULT value to determine an error string to return.

In the C source code, the function declaration is:
extern "C" __declspec(dllexport) HRESULT _stdcall GetErrorMessage(IN HRESULT hr, OUT BSTR MsgOut)

The DLL interface definition is:
HRESULT _stdcall GetErrorMessage([in] int hr,[out,retval] BSTR MsgOut);

When the DLL is selected in LabVIEW's "Call Library function node", it reads the interface definition to generate the function prototype:
long GetErrorMessage(long hr, CStr MsgOut);

The format displayed for parameter MsgOut is "C String Pointer", and cannot be changed away from this
without a LabVIEW warning. The calling convention is "stdcall (WINAPI)" and cannot be changed from this without a LabVIEW warning.

When the string is passed from LabVIEW to the DLL, the pointer MsgOut correctly points to the string, but the 4 bytes immediately preceding the string are all zero, rather than indicating the length of the string. This then causes problems when an attempt is made to point MsgOut from its existing buffer (freed using SysFreeString) to a new buffer (created using SysAllocString) containing the output text.

Can you suggest how I can persuade LabVIEW to generate the string length and insert it where the BSTR definition requires?

Many thanks
Nick
0 Kudos
Message 3 of 4
(3,766 Views)
Nick Hewish wrote:

> The DLL interface definition is:
> HRESULT _stdcall GetErrorMessage([in] int hr,[out,retval] BSTR
> MsgOut);
>
> When the string is passed from LabVIEW to the DLL, the pointer MsgOut
> correctly points to the string, but the 4 bytes immediately preceding
> the string are all zero, rather than indicating the length of the
> string. This then causes problems when an attempt is made to point
> MsgOut from its existing buffer (freed using SysFreeString) to a new
> buffer (created using SysAllocString) containing the output text.
>
> Can you suggest how I can persuade LabVIEW to generate the string
> length and insert it where the BSTR definition requires?

There isn't a direct way in the LabVIEW Call Library Node. BSTR is a
ver
y specific Visual Basic datatype with some strange things to it as
well, such as a rather bad documentation about its inner workings
including the meaning of the hidden prepended length integer (bytes
or chars).

The only possible way I see is to actually allocate and deallocate
the buffer with the according WinAPI calls, really treating it as
a 32 bit integer (pointer) instead of a string in LabVIEW.

Alternative ways would be to create a byte array and do some magic
on it to get at its pointer but that is also quite involved and
actually less intuitive.

Rolf Kalbermatter
Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 4 of 4
(3,766 Views)