OCX(COM) Interop...Passing pointer of structure to function

M

Mingyi

Hi,

I have the following question regarding communicating with a OCX control
using C#. Idon't have access to the ocx code, so my c# code is actually mimic
the behavior of C++ counterparts. Basically, I have problem passing a
structure to a function.

Here is the C++ part code:

//****************************************
typedef struct
{
char TypeID;
char UserName[20];
char Password[20];
char UrlAddress[255];
int iStreamChannel;
bool bDirectDrawMode;
}CONNECT_DATA;

CONNECT_DATA m_ConnectData;

// after initializing m_ConnectData

int ret= InitConnectData((PBYTE)&m_ConnectData);

//****************************************

In C# when I drop this active control to my app, the interface for the
function
InitConnectData has be given as follows

InitConnectData(ref byte)

So the following is what I did in the C# part.

//****************************************

[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi,Pack=8)]
public unsafe struct CONNECT_DATA
{
public byte TypeID;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string UserName;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string Password;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
public string UrlAddress;

public int iStreamChannel;
public bool bDirectDrawMode;

}

CONNECT_DATA connect_data = new CONNECT_DATA();

// After initializing all the fields

IntPtr pnt = Marshal.AllocCoTaskMem(Marshal.SizeOf(connect_data));
try
{
Marshal.StructureToPtr(connect_data, pnt, false);
byte[] buffer = new byte[Marshal.SizeOf(connect_data)];
Marshal.Copy(pnt, buffer, 0, Marshal.SizeOf(connect_data));
int ret = axNetworkCameraLink2.InitConnectData(ref buffer[0]);
}
//****************************************

But it seems that the function never gets the structure right, for it always
gives the wrong return value.

I tried to "Tlbimp" the original DLL, change the IL code so that the
"InitConnectData(uint8&)" becames "InitConnectData(native int)", and in C#
the interface becames "InitConnectData(System.IntPtr)", but error occurs,
stating that

"System.Runtime.InteropServices.COMException
(0x80020005): Type mismatch. at
System.RuntimeType.ForwardCallToInvokeMember(String memberName, BindingFlags
flags, Object target, Int32[] aWrapperTypes, MessageData& msgData)"

I guess it is because uint8 is 8 bit and native int is 32 bit...I really
don't know
what to do now, and I think I must do something wrong...Please help, thanks!
 
G

G Himangi

Dont know about the actual call but I can see a few problems with your
structure definition :

1. The UserName,password and address are defined as ByValTStr (means Ansi or
Uni depending on platform) when in fact they are defined as ANSI in the
original structure.

2. The bDirectDrawMode is defined as bool (which marshals to 4 bytes) but
the origianl structure defines it as smallcase bool which in C++ I think
occupies 1 byte.

---------
- G Himangi, LogicNP Software http://www.ssware.com
Shell MegaPack: GUI Controls For Drop-In Windows Explorer like File/Folder
Browsing Functionality (.Net & ActiveX Editions).
EZNamespaceExtensions: Develop namespace extensions rapidly in .Net and
MFC/ATL/C++
EZShellExtensions: Develop all shell extensions,explorer bars and BHOs
rapidly in .Net & MFC/ATL/C++
---------

Mingyi said:
Hi,

I have the following question regarding communicating with a OCX control
using C#. Idon't have access to the ocx code, so my c# code is actually
mimic
the behavior of C++ counterparts. Basically, I have problem passing a
structure to a function.

Here is the C++ part code:

//****************************************
typedef struct
{
char TypeID;
char UserName[20];
char Password[20];
char UrlAddress[255];
int iStreamChannel;
bool bDirectDrawMode;
}CONNECT_DATA;

CONNECT_DATA m_ConnectData;

// after initializing m_ConnectData

int ret= InitConnectData((PBYTE)&m_ConnectData);

//****************************************

In C# when I drop this active control to my app, the interface for the
function
InitConnectData has be given as follows

InitConnectData(ref byte)

So the following is what I did in the C# part.

//****************************************

[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi,Pack=8)]
public unsafe struct CONNECT_DATA
{
public byte TypeID;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string UserName;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string Password;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
public string UrlAddress;

public int iStreamChannel;
public bool bDirectDrawMode;

}

CONNECT_DATA connect_data = new CONNECT_DATA();

// After initializing all the fields

IntPtr pnt = Marshal.AllocCoTaskMem(Marshal.SizeOf(connect_data));
try
{
Marshal.StructureToPtr(connect_data, pnt, false);
byte[] buffer = new byte[Marshal.SizeOf(connect_data)];
Marshal.Copy(pnt, buffer, 0, Marshal.SizeOf(connect_data));
int ret = axNetworkCameraLink2.InitConnectData(ref
buffer[0]);
}
//****************************************

But it seems that the function never gets the structure right, for it
always
gives the wrong return value.

I tried to "Tlbimp" the original DLL, change the IL code so that the
"InitConnectData(uint8&)" becames "InitConnectData(native int)", and in C#
the interface becames "InitConnectData(System.IntPtr)", but error occurs,
stating that

"System.Runtime.InteropServices.COMException
(0x80020005): Type mismatch. at
System.RuntimeType.ForwardCallToInvokeMember(String memberName,
BindingFlags
flags, Object target, Int32[] aWrapperTypes, MessageData& msgData)"

I guess it is because uint8 is 8 bit and native int is 32 bit...I really
don't know
what to do now, and I think I must do something wrong...Please help,
thanks!
 
M

Mingyi

Hi,

I think the first problem is solved by the declaration
"CharSet=CharSet.Ansi" (I think..)

For the second one, I used to marshall the bool to 1 byte counterpart, but
the problem persists..

Thanks for the reply anyway.


G Himangi said:
Dont know about the actual call but I can see a few problems with your
structure definition :

1. The UserName,password and address are defined as ByValTStr (means Ansi or
Uni depending on platform) when in fact they are defined as ANSI in the
original structure.

2. The bDirectDrawMode is defined as bool (which marshals to 4 bytes) but
the origianl structure defines it as smallcase bool which in C++ I think
occupies 1 byte.

---------
- G Himangi, LogicNP Software http://www.ssware.com
Shell MegaPack: GUI Controls For Drop-In Windows Explorer like File/Folder
Browsing Functionality (.Net & ActiveX Editions).
EZNamespaceExtensions: Develop namespace extensions rapidly in .Net and
MFC/ATL/C++
EZShellExtensions: Develop all shell extensions,explorer bars and BHOs
rapidly in .Net & MFC/ATL/C++
---------

Mingyi said:
Hi,

I have the following question regarding communicating with a OCX control
using C#. Idon't have access to the ocx code, so my c# code is actually
mimic
the behavior of C++ counterparts. Basically, I have problem passing a
structure to a function.

Here is the C++ part code:

//****************************************
typedef struct
{
char TypeID;
char UserName[20];
char Password[20];
char UrlAddress[255];
int iStreamChannel;
bool bDirectDrawMode;
}CONNECT_DATA;

CONNECT_DATA m_ConnectData;

// after initializing m_ConnectData

int ret= InitConnectData((PBYTE)&m_ConnectData);

//****************************************

In C# when I drop this active control to my app, the interface for the
function
InitConnectData has be given as follows

InitConnectData(ref byte)

So the following is what I did in the C# part.

//****************************************

[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi,Pack=8)]
public unsafe struct CONNECT_DATA
{
public byte TypeID;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string UserName;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string Password;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
public string UrlAddress;

public int iStreamChannel;
public bool bDirectDrawMode;

}

CONNECT_DATA connect_data = new CONNECT_DATA();

// After initializing all the fields

IntPtr pnt = Marshal.AllocCoTaskMem(Marshal.SizeOf(connect_data));
try
{
Marshal.StructureToPtr(connect_data, pnt, false);
byte[] buffer = new byte[Marshal.SizeOf(connect_data)];
Marshal.Copy(pnt, buffer, 0, Marshal.SizeOf(connect_data));
int ret = axNetworkCameraLink2.InitConnectData(ref
buffer[0]);
}
//****************************************

But it seems that the function never gets the structure right, for it
always
gives the wrong return value.

I tried to "Tlbimp" the original DLL, change the IL code so that the
"InitConnectData(uint8&)" becames "InitConnectData(native int)", and in C#
the interface becames "InitConnectData(System.IntPtr)", but error occurs,
stating that

"System.Runtime.InteropServices.COMException
(0x80020005): Type mismatch. at
System.RuntimeType.ForwardCallToInvokeMember(String memberName,
BindingFlags
flags, Object target, Int32[] aWrapperTypes, MessageData& msgData)"

I guess it is because uint8 is 8 bit and native int is 32 bit...I really
don't know
what to do now, and I think I must do something wrong...Please help,
thanks!
 
G

G Himangi

I think the first problem is solved by the declaration
"CharSet=CharSet.Ansi" (I think..)
Yes, you are right.

Another problem I noticed was the Pack=8 attribute. Is this type of packing
specified on the original structure? If not, leave it out.

---------
- G Himangi, LogicNP Software http://www.ssware.com
Shell MegaPack: GUI Controls For Drop-In Windows Explorer like File/Folder
Browsing Functionality (.Net & ActiveX Editions).
EZNamespaceExtensions: Develop namespace extensions rapidly in .Net and
MFC/ATL/C++
EZShellExtensions: Develop all shell extensions,explorer bars and BHOs
rapidly in .Net & MFC/ATL/C++
---------

Mingyi said:
Hi,

I think the first problem is solved by the declaration
"CharSet=CharSet.Ansi" (I think..)

For the second one, I used to marshall the bool to 1 byte counterpart, but
the problem persists..

Thanks for the reply anyway.


G Himangi said:
Dont know about the actual call but I can see a few problems with your
structure definition :

1. The UserName,password and address are defined as ByValTStr (means Ansi
or
Uni depending on platform) when in fact they are defined as ANSI in the
original structure.

2. The bDirectDrawMode is defined as bool (which marshals to 4 bytes) but
the origianl structure defines it as smallcase bool which in C++ I think
occupies 1 byte.

---------
- G Himangi, LogicNP Software http://www.ssware.com
Shell MegaPack: GUI Controls For Drop-In Windows Explorer like
File/Folder
Browsing Functionality (.Net & ActiveX Editions).
EZNamespaceExtensions: Develop namespace extensions rapidly in .Net and
MFC/ATL/C++
EZShellExtensions: Develop all shell extensions,explorer bars and BHOs
rapidly in .Net & MFC/ATL/C++
---------

Mingyi said:
Hi,

I have the following question regarding communicating with a OCX
control
using C#. Idon't have access to the ocx code, so my c# code is actually
mimic
the behavior of C++ counterparts. Basically, I have problem passing a
structure to a function.

Here is the C++ part code:

//****************************************
typedef struct
{
char TypeID;
char UserName[20];
char Password[20];
char UrlAddress[255];
int iStreamChannel;
bool bDirectDrawMode;
}CONNECT_DATA;

CONNECT_DATA m_ConnectData;

// after initializing m_ConnectData

int ret= InitConnectData((PBYTE)&m_ConnectData);

//****************************************

In C# when I drop this active control to my app, the interface for the
function
InitConnectData has be given as follows

InitConnectData(ref byte)

So the following is what I did in the C# part.

//****************************************

[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi,Pack=8)]
public unsafe struct CONNECT_DATA
{
public byte TypeID;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string UserName;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string Password;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
public string UrlAddress;

public int iStreamChannel;
public bool bDirectDrawMode;

}

CONNECT_DATA connect_data = new CONNECT_DATA();

// After initializing all the fields

IntPtr pnt =
Marshal.AllocCoTaskMem(Marshal.SizeOf(connect_data));
try
{
Marshal.StructureToPtr(connect_data, pnt, false);
byte[] buffer = new byte[Marshal.SizeOf(connect_data)];
Marshal.Copy(pnt, buffer, 0,
Marshal.SizeOf(connect_data));
int ret = axNetworkCameraLink2.InitConnectData(ref
buffer[0]);
}
//****************************************

But it seems that the function never gets the structure right, for it
always
gives the wrong return value.

I tried to "Tlbimp" the original DLL, change the IL code so that the
"InitConnectData(uint8&)" becames "InitConnectData(native int)", and in
C#
the interface becames "InitConnectData(System.IntPtr)", but error
occurs,
stating that

"System.Runtime.InteropServices.COMException
(0x80020005): Type mismatch. at
System.RuntimeType.ForwardCallToInvokeMember(String memberName,
BindingFlags
flags, Object target, Int32[] aWrapperTypes, MessageData& msgData)"

I guess it is because uint8 is 8 bit and native int is 32 bit...I
really
don't know
what to do now, and I think I must do something wrong...Please help,
thanks!
 

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