[英]Pinvoke struct translation from C++
以下是一些經過驗證的C ++:
typedef struct
{
PVOID buffer;
UINT32 length;
} DATA_BUFFER;
typedef struct
{
DATA_BUFFER TxBuf [1];
DATA_BUFFER RxBuf [1];
} JVM_COMM_BUFFER;
UINT32 SendAndRecv(
IN JHI_HANDLE handle,
IN CHAR* AppId,
INOUT JVM_COMM_BUFFER* pComm
);
以下是我嘗試將其移植到C#的嘗試:
[StructLayout(LayoutKind.Sequential)]
public struct DATA_BUFFER
{
public byte[] buffer;
public uint length;
}
[StructLayout(LayoutKind.Sequential)]
public struct JVM_COMM_BUFFER
{
public DATA_BUFFER TxBuf;
public DATA_BUFFER RxBuf;
}
[DllImport("jhi.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)]
public static extern UInt32 SendAndRecv(IntPtr handle, string AppId, ref JVM_COMM_BUFFER pComm);
封送處理不會在C#中引發異常,但是對於C ++和C#版本,結果是不同的。 對我缺少的東西有任何想法嗎?
問題可能出在您的第一個結構中。 C ++定義包括一個指向數據緩沖區的指針,但Marshaller無法將其直接轉換為.NET byte[]
(或者,如果將其轉換為另一個方向,它可能會將byte[]
轉換為無效的指針,因此您的非法參數是錯誤)。 相反,您可以分兩個步驟手動執行此操作:
[StructLayout(LayoutKind.Sequential)]
public struct DATA_BUFFER
{
public IntPtr buffer;
public uint length;
}
然后使用Marshal
手動讀取緩沖區(這只是我對Marshal
API的記憶中的一個快速示例):
var txBufBytes = new byte[pComm.TxBuf.length];
Marshal.Copy(pComm.TxBuff.buffer, 0, pComm.TxBuf.length);
除此之外,正如注釋中提到的CharSet.Ansi
如果您的本機代碼采用非Unicode /寬字符,則可能需要將CharSet
設置為CharSet.Ansi
。
最后,第二個結構的C ++定義似乎定義了單元素數組,該數組實際上可能是指針,而不是將結構存儲在內存中。 如果是這種情況,您可能必須替換定義以對Interop使用IntPtr
,然后使用Marshal.PtrToStructure
獲取實際結構。
通過比較C ++中的sizeof(...)
和C#中的Marshal.SizeOf(...)
來獲得結構定義,您至少應該比較結構大小是否相同。
鑒於您在注釋中所說的,您應該能夠使用我上面描述的DATA_BUFFER
修改以及用於JVM_COMM_BUFFER
的原始結構定義
[StructLayout(LayoutKind.Sequential)]
struct JVM_COMM_BUFFER
{
public DATA_BUFFER TxBuf;
public DATA_BUFFER RxBuf;
}
結合對DllImport
的輕微修改
[DllImport("jhi.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern UInt32 SendAndRecv(IntPtr handle, string AppId, [In, Out] ref JVM_COMM_BUFFER pComm);
CharSet.Ansi
對於確保將.NET字符串正確地編組為ansi字符串非常重要(假設您的本機C函數不希望使用wchar_t
字符串類型)。 可能不需要[In, Out]
屬性,但可能會提示編組如何正確控制該參數。
如果JVM_COMM_BUFFER
確實是INOUT
,並且在調用該函數之前預先填充了數據,則可能需要確保數據全部有效。 您正在調用的函數可能具有有關其參數期望值的文檔。 但是,此處的定義應根據您提供的C ++定義正確地編組。
問題是僅分配內存和分配固定對象之間的區別。 一旦將其切換到固定對象,則除了緩沖區字段之外,沒有任何IntPtrs的簽名就可以正常工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.