将结构传递给非托管代码

问题描述:

我正在尝试用C#编写一个.NET包装器,用于作为.LIB文件和.h头文件提供的
。我已经完成了大部分

函数的工作,但我真的很难将需要

结构的函数传递给它们。 .h文件中的函数声明是

格式:

SDCERR GetConfig(char * name,SDCConfig * cfg);

其中SDCConfig是.h文件中定义的结构。我不是一个C $ / $
(或C#)程序员,但cfg前面的*表示必须使用ref关键字传递

结构(通过参考)?

我遇到的另一个部分是实际的

结构本身的定义。 .h定义是:

typedef struct _SDCConfig {

char configName [CONFIG_NAME_SZ];

char SSID [SSID_SZ];

int txPower;

....

....

CRYPT WEPKeys;

} SDCConfig;

(其中CRYPT是另一个包含char数组的结构)。无论我看起来如何尝试使用C#定义,我都会在调用函数时获得一个NotSupportedException。我试图在char数组定义的前面使用MarshalAs关键字,这是我在传递

字符串时成功完成的,但说实话我不是真的明白我在做什么!我还要

有另一个包含DWORD和char数组的结构,我不知道该怎么做。我使用的代码是:

[StructLayout。(LayoutKind.Sequential,CharSet = CharSet.Unicode)]

public struct SDCConfig

{

MarshalAs [UnmanagedType.LPArray,SizeConst = CONFIG_NAME_SZ];

public byte [] configName;

...

...

}

我试过玩UnmanagedType.LPArray,并传递

char [],字符串和StringBuilder而不是字节数组,但总是得到

NotSupportedException。我已经尝试通过填充字节数组中的
来初始化结构。我正在使用的电话是:

SDCConfig cfg = new SDCConfig(ConfigName);

SDCERR result = GetConfig(Name,ref cfg);

我正在使用Compact Framework和VS.NET 2005,如果这产生了

的差异。

任何帮助都将不胜感激。在此先感谢。


Andy Baker

I am attempting to write a .NET wrapper in C# for an SDK that has been
supplied as a .LIB file and a .h header file. I have got most of the
functions to work but am really struggling with the functions that require a
structure to be passed to them. The function declaration in the .h file is
of the form:
SDCERR GetConfig(char *name, SDCConfig *cfg);
where SDCConfig is a structure defined in the .h file. I am not much of a C
(or C#) programmer but does the * in front of the cfg signify that the
structure has to be passed using the ref keyword (by reference)?
The other part I am having trouble with is the definition of the actual
structure itself. The .h definition is:
typedef struct _SDCConfig {
char configName[CONFIG_NAME_SZ];
char SSID[SSID_SZ];
int txPower;
....
....
CRYPT WEPKeys;
} SDCConfig;
(where CRYPT is another structure containing a char array). Whatever I seem
to try in the C# definition, I am getting a NotSupportedException when
calling the function. I am attempting to use the MarshalAs keyword in front
of the char array definitions, which I have done successfully when passing
strings, but to be honest I don''t really understand what I am doing! I also
have another structure containing DWORDs as well as char arrays that I don''t
know what to do with. The code I am using is:
[StructLayout.(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct SDCConfig
{
MarshalAs[UnmanagedType.LPArray, SizeConst=CONFIG_NAME_SZ];
public byte[] configName;
...
...
}
I have tried playing about with the UnmanagedType.LPArray, and passing
char[], string, and StringBuilder instead of the byte array, but always get
the NotSupportedException. I have tried initialising the structure by
filling in the byte array. The call I am using is:
SDCConfig cfg = new SDCConfig(ConfigName);
SDCERR result = GetConfig(Name, ref cfg);
I am using the Compact Framework and VS.NET 2005 if that makes a
difference.
Any help would be appreciated. Thanks in advance.

Andy Baker

7月15日,1:20 * pm," ;安迪贝克 < aba ... @ NOSPAMvanputer.comwrote:
On Jul 15, 1:20*pm, "Andy Baker" <aba...@NOSPAMvanputer.comwrote:

我正在尝试用C#编写一个.NET包装器,用于已经
$ b的SDK $ b作为.LIB文件和.h头文件提供。我已经完成了大部分

函数的工作,但我真的很难将需要

结构的函数传递给它们。 .h文件中的函数声明是

格式:

* * SDCERR GetConfig(char * name,SDCConfig * cfg);

其中SDCConfig是.h文件中定义的结构。我不是a $

(或C#)程序员,但cfg前面的*表示必须使用ref关键字传递

结构(通过参考)?
I am attempting to write a .NET wrapper in C# for an SDK that has been
supplied as a .LIB file and a .h header file. I have got most of the
functions to work but am really struggling with the functions that require a
structure to be passed to them. The function declaration in the .h file is
of the form:
* * SDCERR GetConfig(char *name, SDCConfig *cfg);
where SDCConfig is a structure defined in the .h file. I am not much of aC
(or C#) programmer but does the * in front of the cfg signify that the
structure has to be passed using the ref keyword (by reference)?



是的。

Yes.


* *我遇到问题的另一部分是实际的定义

结构本身。 .h定义是:

* * typedef struct _SDCConfig {

* * * * char * * configName [CONFIG_NAME_SZ];

* * * * char * * SSID [SSID_SZ];

* * * * int * txPower;

* * * * ....

* * * * ....

* * * * CRYPT * * WEPKeys;} SDCConfig;


(其中CRYPT是另一个包含char数组的结构)。无论我看起来如何尝试使用C#定义,我都会在调用函数时获得一个NotSupportedException。 *我试图在char数组定义的前面使用MarshalAs关键字,这是我在传递

字符串时成功完成的,但老实说我不喜欢我真的明白我在做什么!我还要

有另一个包含DWORD和char数组的结构,我不知道该怎么做。我使用的代码是:

* * [StructLayout。(LayoutKind.Sequential,CharSet = CharSet.Unicode)]

* * public struct SDCConfig

* * {

* * * * MarshalAs [UnmanagedType.LPArray,SizeConst = CONFIG_NAME_SZ];

* * * * public byte [] configName;

* * * * ...

* * * * ...

* *}
* * The other part I am having trouble with is the definition of the actual
structure itself. The .h definition is:
* * typedef struct _SDCConfig {
* * * * char * *configName[CONFIG_NAME_SZ];
* * * * char * *SSID[SSID_SZ];
* * * * int * txPower;
* * * * ....
* * * * ....
* * * * CRYPT * *WEPKeys;} SDCConfig;

(where CRYPT is another structure containing a char array). Whatever I seem
to try in the C# definition, I am getting a NotSupportedException when
calling the function. *I am attempting to use the MarshalAs keyword in front
of the char array definitions, which I have done successfully when passing
strings, but to be honest I don''t really understand what I am doing! I also
have another structure containing DWORDs as well as char arrays that I don''t
know what to do with. The code I am using is:
* * [StructLayout.(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
* * public struct SDCConfig
* * {
* * * * MarshalAs[UnmanagedType.LPArray, SizeConst=CONFIG_NAME_SZ];
* * * * public byte[] configName;
* * * * ...
* * * * ...
* * }



你确定NotSupportedException是因为[MarshalAs]吗?


无论如何,如果你给出了

的完整定义会有所帮助struct,原始C和C#版本。此外,C#DllImport

声明函数也很方便。

Are you sure the NotSupportedException is because of [MarshalAs]?

Anyway, it would be helpful if you gave the entire definition of the
struct, both the original C, and your C# version. Also, C# DllImport
declaration for the function would be handy, too.


感谢您回复我。
Thanks for getting back to me on this.

>你确定NotSupportedException是因为[MarshalAs]吗?
>Are you sure the NotSupportedException is because of [MarshalAs]?



不,它可能是我想的任何东西!

No, it could be anything I guess!


>无论如何,如果你给出了原始C和C#版本的整个结构定义。此外,C#DllImport
函数声明也很方便。
>Anyway, it would be helpful if you gave the entire definition of the
struct, both the original C, and your C# version. Also, C# DllImport
declaration for the function would be handy, too.



它们如下:

C .h头文件 - 结构


typedef struct _CRYPT {

DWORD大小;

char缓冲区[120];

DWORD偏移量;

} CRYPT;


typedef struct _SDCConfig {

char configName [CONFIG_NAME_SZ];

char SSID [SSID_SZ];

char clientName [CLIENT_NAME_SZ];

int txPower;

AUTH authType;

EAPTYPE eapType;

POWERSAVE powerSave ;

WEPTYPE wepType;

BITRATE bitRate;

RADIOMODE radioMode;

CRYPT userName;

CRYPT userPwd;

CRYPT PSK;

CRYPT WEPKeys;

} SDCConfig


其中一个功能的声明是

SDCERR GetConfig(char * name,SDCCONFIG * cfg);


我的C#代码 - 结构


[StructLayout(LayoutKind.Sequential) ,CharSet = CharSet.Unicode)]

public struct CRYPT

{

public uint size;

[MarshalAs (UnmanagedType.ByValTStr,SizeConst = 120)]

公共字符串缓冲区;

public uint offset;

}
>
[StructLayout(LayoutKind.Sequential,CharSet = CharSet.Unicode)]

public struct SDCConfig

{

[MarshalAs( UnmanagedType.ByValTStr,SizeConst = CONFIG_NAME_SZ)]

public string configName;

[MarshalAs(UnmanagedType.ByValTStr,SizeConst = SSID_SZ)]

public字符串SSID;

[MarshalAs(UnmanagedType.ByValTStr,SizeConst = CLIENT_NAME_SZ)]

public string clientName;

public Int32 txPower;

public AUTH authType;

public EAPTYPE eapType;

public POWERSAVE powerSave;

pu blic WEPTYPE wepType;

public BITRATE bitRate;

public RADIOMODE radioMode;

public CRYPT userName;

public CRYPT userPwd;

公共CRYPT PSK;

公共CRYPT WEPKeys;

}


[DllImport( " VPSummit.dll",CharSet = CharSet.Unicode)]

public static extern SDCERR GetConfig([MarshalAs(Unmanaged.Type.LPArray)]

byte [] name ,参考SDCCONFIG cfg)];


和函数调用是:

public bool ConfigTest

{

string configName =" VANPUTER";

byte [] Name = System.Text.ASCIIEncoding.ASCII.GetBytes(ConfigNam e +

''\ 0 '');

SDCConfig cfg = new SDCConfig();

SDCERR result = GetConfig(Name,cfg);

return(result = SDCERR_SUCCESS);

}


实际上这个特殊的函数没有给我一个NotSupportedException,

并且结果包含SDCERR_SUCCES S,但cfg不包含它应该的

配置值,所以我显然做了一些错误的事情

。其他类型SDCCERR,AUTH,EAPTYPE等定义为

中的枚举,C和C#以及CONFIG_NAME_SZ等都是常量值。我很满意这里的深度,所以任何建议都会非常受欢迎!谢谢。


Andy Baker


They are as follows:
C .h header file - Structures

typedef struct _CRYPT {
DWORD size;
char buffer [120];
DWORD offset;
} CRYPT;

typedef struct _SDCConfig {
char configName[CONFIG_NAME_SZ];
char SSID[SSID_SZ];
char clientName[CLIENT_NAME_SZ];
int txPower;
AUTH authType;
EAPTYPE eapType;
POWERSAVE powerSave;
WEPTYPE wepType;
BITRATE bitRate;
RADIOMODE radioMode;
CRYPT userName;
CRYPT userPwd;
CRYPT PSK;
CRYPT WEPKeys;
} SDCConfig

And the declaration for one of the functions is
SDCERR GetConfig(char *name, SDCCONFIG *cfg);

My C# code - Structures

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct CRYPT
{
public uint size;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 120)]
public string buffer;
public uint offset;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct SDCConfig
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CONFIG_NAME_SZ)]
public string configName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = SSID_SZ)]
public string SSID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CLIENT_NAME_SZ)]
public string clientName;
public Int32 txPower;
public AUTH authType;
public EAPTYPE eapType;
public POWERSAVE powerSave;
public WEPTYPE wepType;
public BITRATE bitRate;
public RADIOMODE radioMode;
public CRYPT userName;
public CRYPT userPwd;
public CRYPT PSK;
public CRYPT WEPKeys;
}

[DllImport("VPSummit.dll", CharSet = CharSet.Unicode)]
public static extern SDCERR GetConfig([MarshalAs(Unmanaged.Type.LPArray)]
byte [] name, ref SDCCONFIG cfg)];

and the function call is:
public bool ConfigTest
{
string configName = "VANPUTER";
byte [] Name = System.Text.ASCIIEncoding.ASCII.GetBytes(ConfigNam e +
''\0'');
SDCConfig cfg = new SDCConfig();
SDCERR result = GetConfig(Name, cfg);
return (result = SDCERR_SUCCESS);
}

Actually this particular function does not give me a NotSupportedException,
and result contains SDCERR_SUCCESS, but cfg does not contain the
configuration values that it should, so I am obviously doing something
wrong. The other types SDCCERR, AUTH, EAPTYPE etc are defined as enums in
both C and C# and CONFIG_NAME_SZ etc are constant values. I am well out of
my depth here, so any advice will be very welcome! Thanks.

Andy Baker



7月15日,7:33 * pm," ;安迪贝克 < aba ... @ NOSPAMvanputer.comwrote:
On Jul 15, 7:33*pm, "Andy Baker" <aba...@NOSPAMvanputer.comwrote:

感谢您回复我。
Thanks for getting back to me on this.

你确定NotSupportedException是因为[MarshalAs]吗?
Are you sure the NotSupportedException is because of [MarshalAs]?



不,它可能是我猜的任何东西!


No, it could be anything I guess!


无论如何,如果你给了它会很有帮助

结构的整个定义,包括原始C和您的C#版本。此外,C#DllImport

函数声明也很方便。
Anyway, it would be helpful if you gave the entire definition of the
struct, both the original C, and your C# version. Also, C# DllImport
declaration for the function would be handy, too.



它们如下:

C .h头文件 - 结构


typedef struct _CRYPT {

* * DWORD * * size;

* * char * * * * * * buffer [120];

* * DWORD * * offset;


} CRYPT;


typedef struct _SDCConfig {

* * char * * * * * * * * * * configName [CONFIG_NAME_SZ];

* * char * * * * * * * * * * SSID [SSID_SZ];

* * char * * * * * * * * * * clientName [CLIENT_NAME_SZ];

* * int * * * * * * * * * * * * txPower;

* * AUTH * * * * * * * * authType;

* * EAPTYPE * * * * * eapType;

* * POWERSAVE * * powerSave;

* * WEPTYPE * * * * * wepType;

* * BITRATE * * * * * * bitRate;

* * RADIOMODE * * radioMode;

* * CRYPT * * * * * * * userName;

* * CRYPT * * * * * * * userPwd;

* * CRYPT * * * * * * * PSK;

* * CRYPT * * * * * * * WEPKeys;


} SDCC onfig


其中一个函数的声明是

SDCERR GetConfig(char * name,SDCCONFIG * cfg);


我的C#代码 - 结构


[StructLayout(LayoutKind.Sequential,CharSet = CharSet.Unicode)]

public struct CRYPT

{

* * public uint size;

* * [MarshalAs(UnmanagedType.ByValTStr,SizeConst = 120)]

* *公共字符串缓冲区;

* * public uint offset;


}


[StructLayout(LayoutKind.Sequential) ,CharSet = CharSet.Unicode)]

public struct SDCConfig

{

* * [MarshalAs(UnmanagedType.ByValTStr,SizeConst = CONFIG_NAME_SZ)]

* * public string configName;

* * [MarshalAs(UnmanagedType.ByValTStr,SizeConst = SSID_SZ)]

* * public string SSID;

* * [MarshalAs(UnmanagedType.ByValTStr,SizeConst = CLIENT_NAME_SZ)]

* * public string clientName;

* * public Int32 txPo wer;

* * public AUTH authType;

* * public EAPTYPE eapType;

* * public POWERSAVE powerSave;

* * public WEPTYPE wepType;

* * public BITRATE bitRate;

* * public RADIOMODE radioMode;

* * public CRYPT userName;

* * public CRYPT userPwd;

* * public CRYPT PSK;

* * public CRYPT WEPKeys;


}


[DllImport(" VPSummit.dll",CharSet = CharSet.Unicode)]

public static extern SDCERR GetConfig([MarshalAs] (Unmanaged.Type.LPArray)]

byte [] name,ref SDCCONFIG cfg)];


和函数调用是:

public bool ConfigTest

{

* * string configName =" VANPUTER";

* * byte [] Name = System。 Text.ASCIIEncoding.ASCII.GetBytes(ConfigNam e +

''\''');

* * SDCConfig cfg = new SDCConfig();

* * SDCERR结果= GetConfig(名称,cfg);

* *返回(结果= SDCERR_SUCCESS);


}


They are as follows:
C .h header file - Structures

typedef struct _CRYPT {
* * DWORD * *size;
* * char * * * * * *buffer [120];
* * DWORD * *offset;

} CRYPT;

typedef struct _SDCConfig {
* * char * * * * * * * * * * configName[CONFIG_NAME_SZ];
* * char * * * * * * * * * * SSID[SSID_SZ];
* * char * * * * * * * * * * clientName[CLIENT_NAME_SZ];
* * int * * * * * * * * * * * *txPower;
* * AUTH * * * * * * * * authType;
* * EAPTYPE * * * * * eapType;
* * POWERSAVE * *powerSave;
* * WEPTYPE * * * * *wepType;
* * BITRATE * * * * * *bitRate;
* * RADIOMODE * *radioMode;
* * CRYPT * * * * * * * userName;
* * CRYPT * * * * * * * userPwd;
* * CRYPT * * * * * * * PSK;
* * CRYPT * * * * * * * WEPKeys;

} SDCConfig

And the declaration for one of the functions is
SDCERR GetConfig(char *name, SDCCONFIG *cfg);

My C# code - Structures

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct CRYPT
{
* * public uint size;
* * [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 120)]
* * public string buffer;
* * public uint offset;

}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct SDCConfig
{
* * [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CONFIG_NAME_SZ)]
* * public string configName;
* * [MarshalAs(UnmanagedType.ByValTStr, SizeConst = SSID_SZ)]
* * public string SSID;
* * [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CLIENT_NAME_SZ)]
* * public string clientName;
* * public Int32 txPower;
* * public AUTH authType;
* * public EAPTYPE eapType;
* * public POWERSAVE powerSave;
* * public WEPTYPE wepType;
* * public BITRATE bitRate;
* * public RADIOMODE radioMode;
* * public CRYPT userName;
* * public CRYPT userPwd;
* * public CRYPT PSK;
* * public CRYPT WEPKeys;

}

[DllImport("VPSummit.dll", CharSet = CharSet.Unicode)]
public static extern SDCERR GetConfig([MarshalAs(Unmanaged.Type.LPArray)]
byte [] name, ref SDCCONFIG cfg)];

and the function call is:
public bool ConfigTest
{
* * string configName = "VANPUTER";
* * byte [] Name = System.Text.ASCIIEncoding.ASCII.GetBytes(ConfigNam e +
''\0'');
* * SDCConfig cfg = new SDCConfig();
* * SDCERR result = GetConfig(Name, cfg);
* * return (result = SDCERR_SUCCESS);

}



这里立刻看错了一件事就是你所有的C结构

使用char字符串(即非Unicode),但你使用CharSet.Unicode

结合UnmanagedType.ByValTStr - 这将使它们全部

用于编组的Unicode,并且扭曲了以下字段的布局

(从现在开始它们突然是它们应该的两倍)。尝试使用CharSet.Ansi取代
,看看是否有帮助。

One thing that immediately looks wrong here is that all your C structs
use char strings (that is, non-Unicode), but you use CharSet.Unicode
combined with UnmanagedType.ByValTStr - that would make them all
Unicode for marshalling, and skew the layout of following fields
(since now they suddenly are twice as far as they ought to be). Try
using CharSet.Ansi instead and see if that helps.