我有两种不同的将 C 代码编码(marshal)到 C# 的实现。
首先C代码是:
int GetVersion(char * pVer, size_t * piSize);
我在 C# 中的第一次尝试(我没有显示 DllImport 部分):
static extern int GetVersion( byte[] ver, ref UIntPtr size );
以及 C# 中的其他尝试:
static extern int GetVersion([MarshalAs(UnmanagedType.LPStr)] StringBuilder ver, ref ulong size);
我从 net 中的不同示例中了解到这些。但我无法断定哪个是正确的。
最佳答案
简而言之:我们总能做到这一点
static extern int GetVersion(IntPtr ver, ref UIntPtr size );
我永远不会写这个,因为我不喜欢它为 A->W 转换生成的内容:
static extern int GetVersion([MarshalAs(UnmanagedType.LPStr)] StringBuilder ver, ref UIntPtr size);
此外,如果这是一个真正的计数字符串,P/Invoke 代码将不起作用,因为它希望在结束后有一个 0。
我通常会写
static extern int GetVersion( byte[] ver, ref UIntPtr size );
您必须首先在其中创建最大大小的 ver
。然后,您可以使用 System.Text.Encoding
中的内容将 ver
转换为字符串。 GetVersion()
几乎肯定会返回一个常量,因此您可以硬编码正确的编码(无论如何可能是 ASCII)。
您很有可能缺少 [DllImport(..., CallingConvention=CallingConvention.Cdecl)]
导致内存损坏,但我实际上无法判断。
错误:不要将 ulong
用于 size_t
。 size_t
在所有支持的平台上都是 UIntPtr
。
评论建议完全不同的签名 GetDevInfo(int Index, DevInfo * pdevInfo);
这是完全不同的事情,显然有一个最佳选择:
const int IDLength = 100;
[StructLayout(LayoutKind.Sequential)]
struct DeviceInfo {
[MarshalAs(UnmanagedType.ByValArray, SizeConst = IDLength)]
byte[] ID;
}
static extern /* I don't know what's here because missing from comment */
GetDevInfo(int index, ref strcut DeviceInfo info);
string GetInfo(int index)
{
var info = new DeviceInfo();
info.ID = new byte[IDLength];
GetDevInfo(info.ID);
return System.Text.Encoding.ASCII.GetString(info.ID, 0, strlen(info.ID));
}
int strlen(byte[] bytes)
{
int i;
for (i = 0; i < bytes.Length && bytes[i] != 0; i++)
;
return i;
}
````
关于c# - 对于此 C 代码,哪种编码方式是正确的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70646780/