Michael
Michael

Reputation: 25

PInvoking function succeeds, not receiving structure values

I have an ANSI DLL which has a function declared as follows:

long GetInfo(
   THE_INFO* pINFO
) 

The structure THE_INFO is declared as follows:

typedef struct tagTHE_INFO
{
   unsigned long dwSize;
   char          szCopyright[64];
   long          nWidth;
   long          nHeight;
   long          nObjectCount;
   int           bThumbnailImage;
   long          nThumbnailImageWidth;
   long          nThumbnailImageHeight;
   int           bThumbnailObject;
   long          nThumbnailObjectWidth;
   long          nThumbnailObjectHeight;
} 
THE_INFO;

The DLL documentation says that all functions use the stdcall calling convention for passing parameters. Further it defines:

unsigned long    As Unsigned 32-bit integer.
char             As Signed 8-bit integer.
long             As Signed 32-bit integer.
int              As Signed 32-bit integer.

A COM wrapper DLL I used years ago is no longer supported and so I have to deal with the DLL directly. I declared the DLL call and structure in my code as follows:

Declare Ansi Function GetInfo Lib "ADLL.dll" (pINFO As THE_INFO) As Integer

<StructLayout(LayoutKind.Sequential)> Friend Class THE_INFO
  Public dwSize As UInteger
  <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=64)>
  Public szCopyright As String
  Public nWidth As Integer
  Public nHeight As Integer
  Public nObjectCount As Integer
  Public bThumbnailImage As Integer
  Public nThumbnailImageWidth As Integer
  Public nThumbnailImageHeight As Integer
  Public bThumbnailObject As Integer
  Public nThumbnailObjectWidth As Integer
  Public nThumbnailObjectHeight As Integer
End Class


Dim Info As New THE_INFO With {.dwSize = 104}
ErrorCode = GetInfo(Info)

The function call succeeds indicating this in returning zero, so at least everything seems to be declared correctly. But when I look into the returned Info structure, all structure members are still reflecting the initial values. But at least the nWidth and nHeight members must have values greater than zero since the underlying data is a valid object.

I think it has something to do with the pinvoking, but I can't explain to me, what I have done wrong.

Upvotes: 0

Views: 94

Answers (1)

Hans Passant
Hans Passant

Reputation: 941970

You would normally declare the structure with the Structure keyword and pass it ByRef:

<StructLayout(LayoutKind.Sequential)> _
Friend Structure THE_INFO
    '' etc..
End Structure

Declare Ansi Function GetInfo Lib "ADLL.dll" (ByRef pINFO As THE_INFO) As Integer

Declaring it as a Class is okay too but then you'll have to pass it ByVal and tell the pinvoke marshaller explicitly that the object needs to be marshaled back. Like this:

Declare Ani Function GetInfo Bar Lib "ADLL.dll" (<[In](), Out()> ByVal pINFO As THE_INFO) As Integer

It is the missing <Out> attribute that is causing your problem. You also need <In> since you initialize the dwSize member of the structure.

Upvotes: 2

Related Questions