我试图使如何在C#中的C ++ DLL之间传递字符串的绝对最简单的最小示例。
我的C ++看起来像这样:
using std::string; extern "C" { string concat(string a, string b){ return a + b; } }
带有标题
using std::string; extern "C" { // Returns a + b __declspec(dllexport) string concat(string a, string b); }
我的C#是
[DllImport("*****.dll", CallingConvention = CallingConvention.Cdecl)] static extern string concat(string a, string b); }
我用以下方式调用它:Console.WriteLine(concat(“ a”,“ b”));
但这给出了System.AccessViolationException。看来这似乎是最琐碎的事情,但是我完全坚持了下来。当我尝试使用“添加”功能进行相似的实验时,该函数进行了两次加倍操作并返回了一次加倍操作,我没有遇到任何问题。
您不能std::string跨互操作边界传递C ++ 。您不能在C#代码中创建其中之一。因此,您的代码将永远无法工作。
std::string
您需要在互操作边界使用互操作友好类型。例如,以null终止的字符数组。当您在同一模块中分配和取消分配内存时,这种方法效果很好。因此,将数据从C#传递到C ++时非常简单。
C ++
void foo(const char *str) { // do something with str }
C#
[DllImport("...", CallingConvention = CallingConvention.Cdecl) static extern void foo(string str); .... foo("bar");
在另一个方向上,您通常希望调用方分配缓冲区,被调用方可以在其中写入以下内容:
void foo(char *str, int len) { // write no more than len characters into str }
[DllImport("...", CallingConvention = CallingConvention.Cdecl) static extern void foo(StringBuilder str, int len); .... StringBuilder sb = new StringBuilder(10); foo(sb, sb.Capacity);