CLI封装涉及内存对齐的结构体时,使用的是StructLayoutAttribute,指定Pack为1、4、8等属性。
【1】C++导出函数,使用 1位对齐
#pragma pack(push) #pragma pack(1) typedef struct _testStru2 { int iVal; char cVal; __int64 llVal; }testStru2; #pragma pack(pop)
//4.2 结构体边界对齐 EXPORTDLL_CLASS void Struct_PackN( testStru2 *pStru ) { if (NULL == pStru) { return; } pStru->iVal = 1; pStru->cVal = 'a'; pStru->llVal = 2; wprintf(L"Struct_PackN \n"); }
CLI封装:
[Serializable] [StructLayoutAttribute(LayoutKind::Sequential, Pack=1)] public ref struct test2 { Int32 iVal; SByte cVal; Int64 llVal; void UnmanagedPtr2ManagedStru(IntPtr ptr) { testStru2 *ptStru = static_cast<testStru2 *>(ptr.ToPointer()); if (NULL == ptStru) return; iVal = ptStru->iVal; cVal = ptStru->cVal; llVal= ptStru->llVal; } };
void ExportCLI::StructCls::StructPackN( test2^ %pStru ) { if (pStru == nullptr) { return; } testStru2 strT; strT.iVal = pStru->iVal; strT.cVal = pStru->cVal; strT.llVal = pStru->llVal; Struct_PackN(&strT); pStru->UnmanagedPtr2ManagedStru(IntPtr(&strT)); }
CLI类声明:
/// <summary> /// 3 结构体测试类 /// </summary> public ref class StructCls { public: /// <summary> /// 3.1 结构体作为输入输出参数 /// </summary> /// <param name="pStru">结构体</param> static void StructChange(test1^ %pStru); /// <summary> /// 3.2 结构体边界对齐 /// </summary> /// <param name="pStru">结构体</param> static void StructPackN(test2^ %pStru); /// <summary> /// 3.3 结构体中含有内置数据类型的数组 /// </summary> /// <param name="pStru">结构体</param> static void StructChangeArr(test3^ %pStru); /// <summary> /// 3.4 union类型中含有结构体 /// </summary> /// <param name="pStru">结构体</param> static void StructUnion(test4^ %pStru); /// <summary> /// 3.5 结构体数组作为参数 /// </summary> /// <param name="pStru">结构体数组</param> static void StructStruArr(List<test5^>^ pStru); };
C#测试程序:
可以看到结构体的长度为13.
test2 tStru2 = new test2(); tStru2.iVal = 0; tStru2.cVal = 0; tStru2.llVal = 0; int size = Marshal.SizeOf(tStru2.GetType()); StructCls.StructPackN(ref tStru2);
源码地址: