[英]How to Marshal a C struct with a byte * field for C# with DLLImport
我試圖弄清楚如何正確地編組一個包含byte *字段的C結構,以便可以從C#應用程序向第三方API發送命令。 但是,我一直在抱怨有關參數的錯誤。 這就是我從C代碼得到的:
struct MY_STRUCT
{
int32 Object; // Object index, dependent of the context
int32 Cmd; // Command code
byte *Params; // pointer to parameters
};
int32 stdcall SendCommand( int32 DeviceId, MY_STRUCT *Cmd );
這是我當前在C#代碼上引用它的方式:
public struct MY_STRUCT
{
public Int32 Object; // Object index, dependent of the context
public Int32 Cmd; // Command code
public IntPtr Params; // pointer to parameters
};
[DllImport("C:\\Client.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern Int32 SendCommand( Int32 DeviceId, ref MY_STRUCT Cmd );
Int32 CSharpSendCommand( int placa, int chan, int code, String parametros )
{
MY_STRUCT cmd = new MY_STRUCT();
cmd.Cmd = code;
cmd.Object = chan;
byte[] bytes = new byte[parametros.Length * sizeof(char)];
System.Buffer.BlockCopy(parametros.ToCharArray(), 0, bytes, 0, bytes.Length);
IntPtr p = Marshal.AllocHGlobal(bytes.Length);
try {
Marshal.Copy(bytes, 0, p, parametros.Length);
cmd.Params = p;
Int32 ret = Translated.SendCommand( placa, ref cmd );
if (ret != (int)LibraryStatus.Success)
Console.Out.Write("Erro: Comando 0x{0} retornou: {1}\n", code, ret);
return ret;
}
finally
{
Marshal.FreeHGlobal(p);
}
}
有什么猜想嗎? 發送基本類型(如Byte,Int32等)時,它的工作原理真的很好。
最可能的問題是您混淆了字節和字符。 特別是,您有以下內容:
byte[] bytes = new byte[parametros.Length * sizeof(char)];
System.Buffer.BlockCopy(parametros.ToCharArray(), 0, bytes, 0, bytes.Length);
IntPtr p = Marshal.AllocHGlobal(bytes.Length);
這實際上是正確的,因為您考慮到char
是兩個字節的長度。 但是然后您有:
Marshal.Copy(bytes, 0, p, parametros.Length);
這是一個問題,因為您只復制了parametros.Length
個字節,這恰好是bytes
數組的一半長度。
我認為您想將其更改為bytes.Length
。
我看到的另一個問題是您沒有提供任何說明該字節序列有多長時間的信息(即沒有cbParams
值或類似值),並且如果應該將其視為字符串,則沒有空終止符。
而且,正如漢斯·帕桑(Hans Passant)所指出的那樣,C代碼不太可能理解一堆2字節的“字符”。 他建議使用Marshal.StringToHGlobalAnsi
可能是對的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.