将结构传递给非托管代码[英] Passing Structures to Unmanaged Code

问题描述

我正在尝试用 C# 为 SDK 编写一个 .NET 包装器
作为 .LIB 文件和 .h 头文件提供.我得到了大部分的
功能可以工作,但我真的在为需要 a
的功能而苦苦挣扎结构传递给他们..h文件中的函数声明为
形式:
SDCERR GetConfig(char *name, SDCConfig *cfg);
其中 SDCConfig 是 .h 文件中定义的结构.我不是一个C
(或 C#)程序员,但 cfg 前面的 * 是否表示
结构必须使用 ref 关键字(通过引用)传递?
我遇到麻烦的另一部分是实际的定义
结构本身..h 定义为:
typedef struct _SDCConfig {
字符配置名称[CONFIG_NAME_SZ];
字符 SSID[SSID_SZ];
int txPower;
....
....
加密 WEP 密钥;
} SDCConfig;
(其中 CRYPT 是另一个包含 char 数组的结构).不管我怎么看
尝试在 C# 定义中,我得到一个 NotSupportedException
调用函数.我正在尝试在前面使用 MarshalAs 关键字
char数组定义,我在传递时已经成功完成
字符串,但说实话,我真的不明白我在做什么!我也是
有另一个包含 DWORD 的结构以及我没有的 char 数组
知道该怎么做.我使用的代码是:
[StructLayout.(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
公共结构 SDCConfig
{
MarshalAs[UnmanagedType.LPArray, SizeConst=CONFIG_NAME_SZ];
公共字节[] configName;
...
...
}
我尝试过使用 UnmanagedType.LPArray,并通过
char[], string, 和 StringBuilder 代替字节数组,但总是get
NotSupportedException.我尝试通过
初始化结构填充字节数组.我正在使用的电话是:
SDCConfig cfg = new SDCConfig(ConfigName);
SDCERR 结果 = GetConfig(Name, ref cfg);
我正在使用 Compact Framework 和 VS.NET 2005,如果这样的话
区别.
任何帮助,将不胜感激.提前致谢.

Andy Baker

推荐答案

7 月 15 日下午 1:20*pm,"Andy Baker"<aba...@NOSPAMvanputer.com 写道:
我正在尝试在 C# 中为已
的 SDK 编写一个 .NET 包装器作为 .LIB 文件和 .h 头文件提供.我得到了大部分的
功能可以工作,但我真的在为需要 a
的功能而苦苦挣扎结构传递给他们..h文件中的函数声明为
形式:
* * SDCERR GetConfig(char *name, SDCConfig *cfg);
其中 SDCConfig 是 .h 文件中定义的结构.我不是一个C
(或 C#)程序员,但 cfg 前面的 * 是否表示
结构必须使用 ref 关键字(通过引用)传递?
是的.
* * 我遇到问题的另一部分是实际的定义
结构本身..h 定义为:
* * typedef struct _SDCConfig {
* * * * char * *configName[CONFIG_NAME_SZ];
* * * * 字符 * *SSID[SSID_SZ];
* * * * int * txPower;
* * * * ....
* * * * ....
* * * * CRYPT * *WEPKeys;} SDCConfig;

(其中 CRYPT 是另一个包含 char 数组的结构).不管我怎么看
尝试在 C# 定义中,我得到一个 NotSupportedException
调用函数.*我正在尝试在前面使用 MarshalAs 关键字
char数组定义,我在传递时已经成功完成
字符串,但说实话,我真的不明白我在做什么!我也是
有另一个包含 DWORD 的结构以及我没有的 char 数组
知道该怎么做.我使用的代码是:
* * [StructLayout.(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
** 公共结构 SDCConfig
* * {
* * * * MarshalAs[UnmanagedType.LPArray, SizeConst=CONFIG_NAME_SZ];
* * * * public byte[] configName;
* * * * ...
* * * * ...
* * }
你确定 NotSupportedException 是因为 [MarshalAs]?

无论如何,如果您给出了
的完整定义,那将会很有帮助struct,原始 C 和您的 C# 版本.另外,C# DllImport
函数声明也很方便.

感谢您回复我.
>你确定 NotSupportedException 是因为 [MarshalAs]?
不,可能是我猜的任何东西!
>无论如何,如果您给出
结构的完整定义,包括原始 C 和您的 C# 版本,将会很有帮助.此外,该函数的 C# DllImport
声明也很方便.
它们如下:
C .h 头文件 - 结构

typedef struct _CRYPT {
双字大小;
字符缓冲区 [120];
DWORD 偏移量;
} 密码;

typedef struct _SDCConfig {
字符配置名称[CONFIG_NAME_SZ];
字符 SSID[SSID_SZ];
char clientName[CLIENT_NAME_SZ];
int txPower;
AUTH authType;
EAPTYPE eapType;
省电省电;
WEPTYPE wepType;
比特率比特率;
RADIOMODE 无线电模式;
加密用户名;
加密用户密码;
加密PSK;
加密 WEP 密钥;
} SDCConfig

其中一个函数的声明是
SDCERR GetConfig(char *name, SDCCONFIG *cfg);

我的 C# 代码 - 结构

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
公共结构 CRYPT
{
公共单位大小;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 120)]
公共字符串缓冲区;
公共单位偏移量;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
公共结构 SDCConfig
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CONFIG_NAME_SZ)]
公共字符串配置名称;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = SSID_SZ)]
公共字符串 SSID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CLIENT_NAME_SZ)]
公共字符串客户端名称;
public Int32 txPower;
public AUTH authType;
公共EAPTYPE eapType;
public POWERSAVE powerSave;
公共 WEPTYPE wepType;
公共比特率比特率;
公共RADIOMODE无线电模式;
公共密码用户名;
公共密码用户密码;
公共密码 PSK;
公共 CRYPT WEPKeys;
}

[DllImport("VPSummit.dll", CharSet = CharSet.Unicode)]
公共静态外部 SDCERR GetConfig([MarshalAs(Unmanaged.Type.LPArray)]
byte [] name, ref SDCCONFIG cfg)];

函数调用为:
公共布尔配置测试
{
string configName = "VANPUTER";
byte [] Name = System.Text.ASCIIEncoding.ASCII.GetBytes(ConfigName +
''\0'');
SDCConfig cfg = new SDCConfig();
SDCERR 结果 = GetConfig(Name, cfg);
返回(结果 = SDCERR_SUCCESS);
}

实际上这个特定的功能并没有给我一个 NotSupportedException,
结果包含SDCERR_SUCCESS,但cfg不包含
应该的配置值,所以我显然在做一些事情
错误的.其他类型 SDCCERR、AUTH、EAPTYPE 等在
中定义为枚举C 和 C# 以及 CONFIG_NAME_SZ 等都是常量值.我已经没有了
我的深度在这里,所以任何建议都将非常受欢迎!谢谢.

Andy Baker



7 月 15 日晚上 7:33*pm,"Andy Baker"<aba...@NOSPAMvanputer.com 写道:
感谢您就此事回复我.
你确定 NotSupportedException 是因为 [MarshalAs] 吗?

不,可能是我猜的任何东西!
无论如何,如果您给出了
的完整定义,那将会很有帮助struct,原始 C 和您的 C# 版本.另外,C# DllImport
函数的声明也很方便.

它们如下:
C .h 头文件 - 结构

typedef struct _CRYPT {
* * DWORD * * 大小;
* * char * * * * * *buffer [120];
* * DWORD * *偏移量;

} 密码;

typedef struct _SDCConfig {
* * char * * * * * * * * * * configName[CONFIG_NAME_SZ];
* * char * * * * * * * * * * SSID[SSID_SZ];
* * char * * * * * * * * * * clientName[CLIENT_NAME_SZ];
* * int * * * * * * * * * * * *txPower;
* * AUTH * * * * * * * * authType;
* * EAPTYPE * * * * * eapType;
* * 省电 * *省电;
* * WEPTYPE * * * * *wepType;
* * 比特率 * * * * * *比特率;
* * RADIOMODE * *radioMode;
* * CRYPT * * * * * * * 用户名;
* * CRYPT * * * * * * * userPwd;
* * 加密 * * * * * * * PSK;
* * CRYPT * * * * * * * WEPKeys;

} SDCConfig

其中一个函数的声明是
SDCERR GetConfig(char *name, SDCCONFIG *cfg);

我的 C# 代码 - 结构

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
公共结构 CRYPT
{
** 公共单位大小;
* * [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 120)]
** 公共字符串缓冲区;
** 公共 uint 偏移量;

}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
公共结构 SDCConfig
{
* * [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CONFIG_NAME_SZ)]
** 公共字符串配置名称;
* * [MarshalAs(UnmanagedType.ByValTStr, SizeConst = SSID_SZ)]
** 公共字符串 SSID;
* * [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CLIENT_NAME_SZ)]
** 公共字符串客户端名称;
* * public Int32 txPower;
* * public AUTH authType;
* * public EAPTYPE eapType;
* * public POWERSAVE powerSave;
* * public WEPTYPE wepType;
* * 公共比特率比特率;
* * public RADIOMODE radioMode;
* * public CRYPT 用户名;
** public CRYPT userPwd;
** 公共 CRYPT PSK;
* * 公共 CRYPT WEPKeys;

}

[DllImport("VPSummit.dll", CharSet = CharSet.Unicode)]
公共静态外部 SDCERR GetConfig([MarshalAs(Unmanaged.Type.LPArray)]
byte [] name, ref SDCCONFIG cfg)];

函数调用为:
公共布尔配置测试
{
* * string configName = "VANPUTER";
* * byte [] Name = System.Text.ASCIIEncoding.ASCII.GetBytes(ConfigName +
''\0'');
* * SDCConfig cfg = new SDCConfig();
* * SDCERR 结果 = GetConfig(Name, cfg);
* * 返回(结果 = SDCERR_SUCCESS);

}
这里立即看起来不对的一件事是你所有的 C 结构
使用 char 字符串(即非 Unicode),但你使用 CharSet.Unicode
结合 UnmanagedType.ByValTStr - 这将使它们全部
用于编组的 Unicode,并倾斜以下字段的布局
(因为现在他们突然比他们应该的两倍远).试试
改用 CharSet.Ansi 看看是否有帮助.

本文地址:https://www.itbaoku.cn/post/1050732.html