调用一个非托管函数char返回一个char*我在非托管C/C++代码(dll)中有一个函数返回包含char数组的结构。我创建了C#结构来接收调用函数的返回值。并且调用这个函数得到'System.Runtime.InteropServices.MarshalDirectiveException'这是C声明:typedefstructT_SAMPLE_STRUCT{intnum;字符文本[20];}样本结构;SAMPLE_STRUCT样本函数(SAMPLE_STRUCTss);这是C#声明:structSAMPLE_STRUCT{publicintnum;公共字符串文本;}classDllwrapper{[DllImport("samplecdll.dll")]publicstaticexternSAMPLE_STRUCTsampleFunction(SAMPLE_STRUCTss);我使用1字节的ASCII。有没有人有关于如何做到这一点的提示或解决方案?转换C数组成员的技巧是使用MarshalAs(UnmanagedType.ByValTStr)。这可用于告诉CLR将数组封送为内联成员而不是普通的非内联数组。请尝试以下签名。[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential,CharSet=System.Runtime.InteropServices.CharSet.Ansi)]publicstructT_SAMPLE_STRUCT{///intpublicintnum;///char[20][System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr,SizeConst=20)]publicstringtext;}publicpartialclassNativeMethods{///返回类型:SAMPLE_STRUCT->T_SAMPLE_STRUCT///ss:SAMPLE_STRUCT->T_SAMPLE_STRUCT[System.Runtime.InteropServices.DllImportAttribute("",EntryPoint="sampleFunction")]publicstaticexternT_SAMPLE_STRUCTsampleFunction(T_SAMPLE_STRUCTss);}此签名由CodePlex(上的PInvokeInteropAssistant提供。它可以自动将大多数PInvoke签名从本机代码转换为C#或VB.Net。对于P/Invoke编组来说,它不是一个简单的结构:编组结构更容易包含一个char*而不是一个char[](尽管您的问题是从非托管代码分配一个char*,然后从托管代码中释放它)。假设您坚持当前的设计,一种选择是将字符串数组声明为:publicfixedchartext[20];不幸的是,您必须将unsafe关键字添加到访问该数组的任何代码中。C中的结构定义:#pragmapack(push,1)typedefstructT_SAMPLE_STRUCT{intnum;字符文本[20];};#pragmapack(pop)在C#中的定义:[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi,Pack=1)]publicstructT_SAMPLE_STRUCT{[MarshalAs(UnmanagedType.I4)]publicintnum;[MarshalAs(UnmanagedType.ByValTStr,SizeConst=20)]公共字符串文本;我设法通过将函数分成以下部分来做到这一点:voidreceiveStruct(SAMPLE_STRUCTss)voidreturnStruct(SAMPLE_STRUCT&ss)我更改了结构定义,因为JaredPar告诉我:[StructLayoutAttribute(LayoutKind.Sequential,CharSet=CharSet.Ansi)]公共结构T_SAMPLE_STRUCT{///int;num///char[20][MarshalAsAttribute(UnmanagedType.ByValTStr,SizeConst=20)]publicstringtext;现在可以了。谢谢!有趣的是,既然您已经有了答案,这里的基本问题是结构只需要大小合适。由于托管类型没有内联数组,您只需弥补您本来需要的空间。在使用C++/CLI编写时,您会经常看到带有显式Size参数的StructLayoutAttribute。这使得运行时为类型分配适当数量的内存,这使得它对本机端来说是blittable的。所以这些也应该有效:[StructLayout(LayoutKind.Sequential,Size=24)]publicstructT_SAMPLE_STRUCT{publicintnum;//要在此处获取字符串,您需要获取一个指针publiccharfirstChar;}//或[StructLayout(LayoutKind.Sequential)]publicstructT_SAMPLE_STRUCT{publicintnum;公共字节c0;公共字节c1;公共字节c2;公共字节c3;公共字节c4;公共字节c5;公共字节c6;公共字节c7;公共字节c8;公共字节c9;公共字节c10;公共字节c11;公共字节c12;公共字节c13;公共字节c14;公共字节c15;公共字节c16;公共字节c17;公共字节c18;公共字节c19;这些在托管代码中使用起来要困难得多(您需要复制内存或使用指针),但它们说明了blittable类型的概念,主要是类型在本机代码和托管代码之间传递的方式。首先你得给struct加上StructLayout[Sequential]属性,我觉得行得通以上是C#学习教程:调用unmanagedfunctionchar返回char*share的全部内容,如果对大家有用需要了解更多关于C#学习教程,希望大家多多关注——[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi)]structSAMPLE_STRUCT{publicintnum;[MarshalAs(UnmanagedType.ByValArray,SizeConst=20)]publicchar[]text;}本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
