C++ 定義了包含指針的結構體:
typedef struct { BYTE byIndex; BYTE byRW; } PACKET;
typedef struct { PACKET* pPackets; INT32 iNumPackets; } BLOCK;
BOOL Transfer(BLOCK block);
需要在 C# 中正確定義結構體並調用 Transfer 函數。
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct PACKET
{
public byte byIndex;
public byte byRW;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct BLOCK
{
// 關鍵:使用 IntPtr 表示指針,配合 MarshalAs 指定數組封送方式
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]
public PACKET[] pPackets; // C# 數組自動封送為連續內存塊
public int iNumPackets; // 數組長度,對應 SizeParamIndex=1
}
[DllImport("YourCppDll.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern bool Transfer(ref BLOCK block); // 注意:C++ 傳值結構體較大時常用引用/指針,這裡用 ref 模擬
// 調用示例
public bool CallTransfer(PACKET[] packets)
{
BLOCK block = new BLOCK();
block.pPackets = packets;
block.iNumPackets = packets.Length;
return Transfer(ref block);
}
Pack = 1 對應 C++ #pragma pack(1),確保字節對齊一致。PACKET* pPackets 配合長度字段,在 C# 直接用數組 PACKET[] 加 MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1),運行時自動分配非托管內存並拷貝數據。__cdecl,C# 需顯式指定 CallingConvention.Cdecl。BOOL Transfer(BLOCK block)(傳值),C# 用 ref BLOCK 或 out BLOCK;若為 BOOL Transfer(BLOCK* block),C# 用 IntPtr 手動 Marshal.StructureToPtr。Marshal.FreeHGlobal)。[DllImport("CppDll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool Transfer(IntPtr pBlock); // 對應 BLOCK*
public unsafe bool TransferPackets(PACKET[] packets)
{
fixed (PACKET* p = packets)
{
BLOCK block = new BLOCK { pPackets = (IntPtr)p, iNumPackets = packets.Length };
IntPtr pBlock = Marshal.AllocHGlobal(Marshal.SizeOf());
Marshal.StructureToPtr(block, pBlock, false);
bool ret = Transfer(pBlock);
Marshal.FreeHGlobal(pBlock);
return ret;
}
}