调用非托管函数char返回char *
我在非托管C / C ++代码(dll)中有一个函数,它返回一个包含char数组的结构。 我创建了C#struct来接收调用该函数的返回值。 并且调用此函数的uppon得到’System.Runtime.InteropServices.MarshalDirectiveException’
这是C声明:
typedef struct T_SAMPLE_STRUCT { int num; char text[20]; } SAMPLE_STRUCT; SAMPLE_STRUCT sampleFunction( SAMPLE_STRUCT ss );
这是C#声明:
struct SAMPLE_STRUCT { public int num; public string text; } class Dllwrapper { [DllImport("samplecdll.dll")] public static extern SAMPLE_STRUCT sampleFunction(SAMPLE_STRUCT ss); }
我使用1字节ASCII。
有没有人有如何做到这一点的提示或解决方案?
转换C数组成员的技巧是使用MarshalAs(UnmanagedType.ByValTStr)。 这可以用来告诉CLR将数组编组为内联成员与普通非内联数组。 请尝试以下签名。
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, CharSet=System.Runtime.InteropServices.CharSet.Ansi)] public struct T_SAMPLE_STRUCT { /// int public int num; /// char[20] [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst=20)] public string text; } public partial class NativeMethods { /// Return Type: SAMPLE_STRUCT->T_SAMPLE_STRUCT ///ss: SAMPLE_STRUCT->T_SAMPLE_STRUCT [System.Runtime.InteropServices.DllImportAttribute("", EntryPoint="sampleFunction")] public static extern T_SAMPLE_STRUCT sampleFunction(T_SAMPLE_STRUCT ss) ; }
此签名由CodePlex上提供的PInovke Interop Assistant( 链接 )提供给您。 它可以自动将大多数PInvoke签名从本机代码转换为C#或VB.Net。
对于P / Invoke编组来说,这不是一个简单的结构:它更容易编组包含char *而不是char []的结构(尽管你的问题是从非托管代码中分配char *然后从中释放它托管代码)。
假设您坚持使用当前设计,一个选项是将字符串数组声明为:
public fixed char text[20];
不幸的是,您必须将unsafe
关键字添加到访问此数组的任何代码中。
C中的结构定义:
#pragma pack(push, 1) typedef struct T_SAMPLE_STRUCT { int num; char text[20]; }; #pragma pack(pop)
C#中的定义:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] public struct T_SAMPLE_STRUCT { [MarshalAs(UnmanagedType.I4)] public int num; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)] public string text; }
我已经设法通过将function分离到:
void receiveStruct( SAMPLE_STRUCT ss ) void returnStruct(SAMPLE_STRUCT &ss)
我改变了结构定义,因为JaredPar告诉我:
[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct T_SAMPLE_STRUCT { /// int public int num; /// char[20] [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 20)] public string text; }
现在它有效。
谢谢!
有趣的是,既然你已经有了答案,那么这里的基本问题是结构只需要合适的大小。 由于托管类型没有内联数组,因此您只需要弥补原本需要的空间。 在C ++ / CLI中编写时,您经常会看到带有显式Size参数的StructLayoutAttribute。 这使得运行时为该类型分配了适当的内存量,这使得它可以对本机端进行blittable。 因此,这些也应该有效:
[StructLayout(LayoutKind.Sequential, Size=24)] public struct T_SAMPLE_STRUCT { public int num; // to get the string here, you'd need to get a pointer public char firstChar; } // or [StructLayout(LayoutKind.Sequential)] public struct T_SAMPLE_STRUCT { public int num; public byte c0; public byte c1; public byte c2; public byte c3; public byte c4; public byte c5; public byte c6; public byte c7; public byte c8; public byte c9; public byte c10; public byte c11; public byte c12; public byte c13; public byte c14; public byte c15; public byte c16; public byte c17; public byte c18; public byte c19; }
当然,这些在托管代码中使用起来要困难得多(您需要复制内存或使用指针),但它们说明了blittable类型的概念,主要是在本机代码和托管代码之间传递类型的方式。
首先,你必须在struct上放置StructLayout [Sequential]属性,我认为它会起作用
上述就是C#学习教程:调用非托管函数char返回char *分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
[ StructLayout( LayoutKind.Sequential, CharSet=CharSet.Ansi )] struct SAMPLE_STRUCT { public int num; [ MarshalAs( UnmanagedType.ByValArray, SizeConst=20 )] public char[] text; }
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1033477.html