BSTR* marshalling

A

Andrew Merisanu

Hello All,

I have to call a C API function decalred as:
ing GetParameters(int DeviceID, BSTR *ParametersXML)

I tried to do this using the following DLLImport:
<DllImport("avlcontroller.dll", EntryPoint:="GetParameters")> _

Public Shared Function GetParameters(ByVal DeviceId As Integer, ByRef
ParametersXmlPtr As System.IntPtr) As Integer

End Function

This works in that the correct data is returned. However, I have a memory
leak that I cannot seem to find. It's definetly not in the API because we
tested calling it from C++ and it works fine.

Is my declaration correct? Is there something I should be doing differently?

TIA

Andrew
 
A

Alex Feinman [MVP]

You need to release the BSTR by calling SysFreeString once you have
converted it to string
 
A

Andrew Merisanu

Should I call the SysFreeString on the IntPtr variable? because I tried that
and we get an error saying Invalid Pointer.

THanks

Andrew
 
P

Peter Foot [MVP]

Call it from your managed code after youve got the string e.g.

<DllImport("oleaut32.dll")> _
Public Shared Function SysFreeString(ByVal ptr As Ptr) As Integer
End Function

Dim ptr As IntPtr = IntPtr.Zero
GetParameters(id, ptr)
Dim param As String = Marshal.PtrToStringUni(ptr)
SysFreeString(ptr)


Peter
 
A

Andrew Merisanu

Hey Peter,

Thanks for the code sample. We tried the exact same code. There are no
errors, but the memory still increases by 16K on every iteration.

Thanks again,

Andrew
 
A

Alex Feinman [MVP]

How are you measuring the memory? Could it be that the 16k is actually
managed memory that will be freed when GC gets around to doing it?
 
A

Andrew Merisanu

Hey Alex,

We are monitoring the memory usage on the CE device.
I guess it could be managed memory but I don't think so. It never gets freed
even when calling GC. It just keeps growing untill the device locks up from
lack of memory.

We've also tried calling a different function that has a similar signature
but returns a much larger string and the memory grows by over 100K each
time. We've tgried both in VB.NET and C# with similar results.

It's quite frustrating :)

Thanks,

Andrew
 
P

Paul G. Tobey [eMVP]

Can we look at a few other possibilities? What if you *don't* call
Marshal.PtrToStringUni()? Any difference?

Paul T.
 
A

Andrew Merisanu

Hey Paul,

Actually, yes. If I comment out the PtrToStringUni, the memory stays stable.
Hmm.

It soes reduce the usefulness of the function some :)
What does this mean though?
 
P

Paul G. Tobey [eMVP]

At a guess, I'd say that they are allocating some unmanaged memory, or,
maybe, some managed memory that never has its last reference released.
Another possibility that comes to mind is that you are passing it something
that it's not expecting: a BSTR. Note that, in the full framework, there's
a method for doing thing with a BSTR, PtrToStringBSTR(), but it doesn't seem
to be implemented in the Compact Framework.

I suppose that you could write your own version...

Paul T.
 
A

Alex Feinman [MVP]

How about replacing it with the following code:

int nLen = SysStringLen(ptr) ' Needs to be pinvoked
Dim buffer() as Byte = new Byte(nLen * 2) ' or whatever VB syntax is
Marshal.Copy(ptr, buffer, 0, nLen * 2)
str = Encoding.Unicode.GetString(buffer)

I suggest that you also carefully check the nLen value there to see that
it's reasonable
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top