Unmanaged C dll call

B

Bob Simoneau

I am trying to get a C DLL to work with VB.NET 2005. Below is the original
header, my conversion, and test code. There is no error, but
RVERSION_RESP.version returns empty. I must be missing something. Thanks
in advance for any help.


#define REQUEST_DECLINED -2

typedef struct rversion_parms_set_1 RVERSION_PARMS;
typedef struct rversion_resp_set_1 RVERSION_RESP;

#pragma pack(1)

struct rversion_parms_set_1
{
int size; /* REQUIRED Size of structure */
};

struct rversion_resp_set_1
{
int size; /* REQUIRED Size of structure */
int return_code; /* = 0 if no error, != 0 if error */
char return_text[200]; /* Contains error text if return code != 0 */
char version[11]; /* DLL version */
};


#pragma pack()


_declspec(dllexport) extern void rversion(RVERSION_PARMS *rversion_parms,
RVERSION_RESP *rversion_resp);



Module Module1
Public Structure TRVERSION_PARMS
Dim size As Integer ' REQUIRED Size of structure
End Structure

Public Structure TRVERSION_RESP
Dim size As Short ' REQUIRED Size of structure
Dim return_code As Short ' 0 if ( no error, != 0 if ( error
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=200)> _
Dim return_text() As Char ' Contains error text if return code !=
0
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=11)> _
Dim version() As Char ' DLL version
End Structure

Public RVERSION_PARMS As TRVERSION_PARMS
Public RVERSION_RESP As TRVERSION_RESP

Public Declare Function rversion Lib "c:\remotapi.dll" (ByRef
RVERSION_PARMS As TRVERSION_PARMS, ByRef RVERSION_RESP As TRVERSION_RESP) As
Integer

End Module


Test
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
RVERSION_PARMS.size = Marshal.SizeOf(RVERSION_PARMS)
RVERSION_RESP.size = Marshal.SizeOf(RVERSION_RESP)
rversion(RVERSION_PARMS, RVERSION_RESP)
If (RVERSION_RESP.return_code <> 0) Then
TextBox1.Text = "RVERSION ERROR: " & RVERSION_RESP.return_text
Else
TextBox1.Text = "RVERSION: " & RVERSION_RESP.version
End If
End Sub
 
P

Peter Huang [MSFT]

Hi Bob,

The int in C++ means a 32bit data type.
But the Short in VB.NET is 16bit data type.

So I think we need to change the definition in the VB.NET signature.
Here is what works at my side for your reference.
Public Structure TRVERSION_PARMS
Dim size As Integer ' REQUIRED Size of structure
End Structure

Public Structure TRVERSION_RESP
Dim size As Integer ' REQUIRED Size of structure
Dim return_code As Integer ' 0 if ( no error, != 0 if ( error
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=200)> _
Dim return_text() As Char ' Contains error text if return code !=
0
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=11)> _
Dim version() As Char ' DLL version
End Structure

Public RVERSION_PARMS As TRVERSION_PARMS
Public RVERSION_RESP As TRVERSION_RESP

Public Declare Function fnTestDLL Lib "TestDLL.dll" (ByRef
RVERSION_PARMS As TRVERSION_PARMS, ByRef RVERSION_RESP As TRVERSION_RESP)
As Integer

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
RVERSION_PARMS.size = Marshal.SizeOf(RVERSION_PARMS)
RVERSION_RESP.size = Marshal.SizeOf(RVERSION_RESP)
MsgBox(fnTestDLL(RVERSION_PARMS, RVERSION_RESP).ToString())
If (RVERSION_RESP.return_code <> 0) Then
TextBox1.Text = "RVERSION ERROR: " & RVERSION_RESP.return_text
Else
TextBox1.Text = "RVERSION: " & RVERSION_RESP.version
End If
End Sub


[C++]
TESTDLL_API int fnTestDLL(RVERSION_PARMS *rversion_parms, RVERSION_RESP
*rversion_resp)
{
rversion_resp->return_code = 0;
strcpy(rversion_resp->return_text,"Hello");
strcpy(rversion_resp->version,"World");
return 42;
}
ifdef TESTDLL_EXPORTS
#define TESTDLL_API __declspec(dllexport)
#else
#define TESTDLL_API __declspec(dllimport)
#endif

// This class is exported from the TestDLL.dll
class TESTDLL_API CTestDLL {
public:
CTestDLL(void);
// TODO: add your methods here.
};

#define REQUEST_DECLINED -2

typedef struct rversion_parms_set_1 RVERSION_PARMS;
typedef struct rversion_resp_set_1 RVERSION_RESP;

#pragma pack(1)

struct rversion_parms_set_1
{
int size; /* REQUIRED Size of structure */
};

struct rversion_resp_set_1
{
int size; /* REQUIRED Size of structure */
int return_code; /* = 0 if no error, != 0 if error */
char return_text[200]; /* Contains error text if return code != 0 */
char version[11]; /* DLL version */
};


#pragma pack()


extern TESTDLL_API int nTestDLL;

extern "C" TESTDLL_API int fnTestDLL(RVERSION_PARMS *rversion_parms,
RVERSION_RESP *rversion_resp);



Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
B

Bob Simoneau

I now get this response from the DLL;
Rversion response structure has bad size.

Here is the function call:
Public Declare Function rversion Lib "c:\remotapi.dll" (ByRef RVERSION_PARMS
As TRVERSION_PARMS, ByRef RVERSION_RESP As TRVERSION_RESP) As Integer

There is something going on a am unaware of, if I write the structure in C
or Delphi, it is 219 bytes long, and the DLL works. However in VB.net the
structure is 220. If I lower the SizeConst to 198 vise 199, the structure
size drops to 216. I tried using byte instead, and got the same result. I am
lost..... Notice the packed record in Delphi, and the #pragma pack(1) in the
C header. Could this have something to do with it?
Public Structure TRVERSION_RESP
Dim size As Integer ' REQUIRED Size of structure
Dim return_code As Integer ' 0 if no error, != 0 if error
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=199)> _
Dim return_text() As Char ' Contains error text if return code !=
0
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=10)> _
Dim version() As Char ' DLL version
End Structure

This stucture in Delphi as a size of 219 and works with the DLL
type
TRVERSION_RESP = packed record
size: Integer; // REQUIRED Size of structure
return_code: Integer; // 0 if no error, != 0 if error
return_text: array[0..199] of Char; // Contains error text if return
code != 0
version: array[0..10] of Char; // DLL version
end;

Here is the original C header declaration.
#pragma pack(1)
struct rversion_resp_set_1
{
int size; /* REQUIRED Size of structure */
int return_code; /* = 0 if no error, != 0 if error */
char return_text[200]; /* Contains error text if return code != 0 */
char version[11]; /* DLL version */
};
 
P

Peter Huang [MSFT]

Hi Bob,

Have you tried my code in my last post?
Because that works at my side, if we test on your side, it will help us to
isolate the problem.

For your comment about the size of the structure.
I think it may be align problem.
align (C++)
http://msdn2.microsoft.com/en-us/library/83ythb65.aspx

Also in .NET we have a similar attribute StructLayoutAttribute.Pack Field,
you may try to change them to see if that will help you.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/
frlrfsystemruntimeinteropservicesstructlayoutattributeclasspacktopic.asp

If that still did not works for you, can you send me a reproduce
sample?(C++ and VB.NET code including the source code, I am not familar
with delphi)
You can reach me by removing "online" from my email address.


Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
B

Bob Simoneau

I did run your example, and it worked. Thank you so much for your help. I
finally achieved success by adding the line below to the top of the
structure. You hit it right on the head, it was an align problem. The pack=1
solved it.

Successful Line added.

<StructLayout(LayoutKind.Sequential, Pack:=1, CharSet:=CharSet.Ansi)> _
 
P

Peter Huang [MSFT]

Hi Bob,

Thanks for your update.

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 

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