LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Calling a DLL taking a BSTR from LabVIEW

I'm calling a DLL function 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 the DLL tries to free the existing buffer (using SysFreeString) before assigning MsgOut 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?
0 Kudos
Message 1 of 7
(3,878 Views)
Nick,

I am looking into your problem, to save some time could you attach a simplified version of the dll for me to look at.

Kind Regards

Tristan
Applications Engineer
National Instruments
0 Kudos
Message 2 of 7
(3,878 Views)
Hi,

LabVIEW passes a pointer to the string. The passed string is a "C" type
string (pointer to the first character, and NULL at the end).

If the pointer has to point to the length of the string, you can put the
length in the first characters. Just set the string to hex view, and make
the first characters the length of the string (minus the characters used for
the length).

Reverse is similar, the returned string should begin with the length of the
string, causing problems when it begins with 0, because LabVIEW sees this as
the end of the string (this does not happen when a string is passed to a
dll, only when returning a string).

This type of string passing can also be done automatically, by passing
pascal type strings. So if you want to pass a string with the length before
it, pass the string as a pascal type. I do think the pointer points to the
begin of the length, not to the begin of the string. Also, the string might
not be null terminated. A mistake with this will cause LabVIEW to return
error messages.

Hope it helps,

Wiebe.

"Nick Hewish" wrote in message
news:5065000000080000003ADF0000-1079395200000@exchange.ni.com...
> I'm calling a DLL function 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 the DLL tries to free the
> existing buffer (using SysFreeString) before assigning MsgOut 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?
0 Kudos
Message 3 of 7
(3,878 Views)
Wiebe@CARYA wrote:
> Hi,
>
> LabVIEW passes a pointer to the string. The passed string is a "C" type
> string (pointer to the first character, and NULL at the end).
>
> If the pointer has to point to the length of the string, you can put the
> length in the first characters. Just set the string to hex view, and make
> the first characters the length of the string (minus the characters used for
> the length).

Unfortunately a BSTR pointer points to the actual string in the buffer
but the buffer is 4 bytes longer and those 4 bytes are prepended to the
buffer and contain the number of bytes in it eventhough it may be a
widechar buffer.

So it looks an smells like the pointer inside a LabVIEW string handle
but is not really the same.

Rolf Kalbermatter
Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 4 of 7
(3,878 Views)
Wiebe@CARYA wrote:

> Hi,
>
> LabVIEW passes a pointer to the string. The passed string is a "C" type
> string (pointer to the first character, and NULL at the end).
>
> If the pointer has to point to the length of the string, you can put the
> length in the first characters. Just set the string to hex view, and make
> the first characters the length of the string (minus the characters used for
> the length).

And they are supposed to be allocated and deallocated by the
SysAllocString() and friends functions. Failing to do so may result in
crashes as the called function may actually attempt to resize a string
with these functions and that would miserably fail if they were not
allocated with the same functions.

Rolf Kalbermatter
Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 5 of 7
(3,877 Views)
"RolfK" wrote in message
news:40e90c1f@newsgroups....
> Wiebe@CARYA wrote:
>
> > Hi,
> >
> > LabVIEW passes a pointer to the string. The passed string is a "C" type
> > string (pointer to the first character, and NULL at the end).
> >
> > If the pointer has to point to the length of the string, you can put the
> > length in the first characters. Just set the string to hex view, and
make
> > the first characters the length of the string (minus the characters used
for
> > the length).
>
> And they are supposed to be allocated and deallocated by the
> SysAllocString() and friends functions. Failing to do so may result in
> crashes as the called function may actually attempt to resize a string
> with these fun
ctions and that would miserably fail if they were not
> allocated with the same functions.
>
> Rolf Kalbermatter

So all he has to do is use SysAllocStringLen to allocate a string, and pass
the resulting BSTR to the function?

Regards,

Wiebe.
0 Kudos
Message 6 of 7
(3,877 Views)
Wiebe@CARYA wrote:

>>And they are supposed to be allocated and deallocated by the
>>SysAllocString() and friends functions. Failing to do so may result in
>>crashes as the called function may actually attempt to resize a string
>>with these functions and that would miserably fail if they were not
>>allocated with the same functions.
>>
>>Rolf Kalbermatter
>
>
> So all he has to do is use SysAllocStringLen to allocate a string, and pass
> the resulting BSTR to the function?

I haven't tried this but in principle that is the idea. There are of
course still some things to investigate. Such as if the prepended length
is the length of the buffer or the length of the string in the buffer.
If it is the first then how is the end of string in
dicated, probably a 0
char?

You see there are some issues to investigate but with a little trial and
error that could be resolved.

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