BSTR* marshalling

  • Thread starter Thread starter Andrew Merisanu
  • Start date Start date
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
 
You need to release the BSTR by calling SysFreeString once you have
converted it to string
 
Should I call the SysFreeString on the IntPtr variable? because I tried that
and we get an error saying Invalid Pointer.

THanks

Andrew
 
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
 
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
 
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?
 
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
 
Can we look at a few other possibilities? What if you *don't* call
Marshal.PtrToStringUni()? Any difference?

Paul T.
 
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?
 
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.
 
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
 
Back
Top