一尘不染

将字符串从C#传递到C ++ DLL并返回-最小的例子

c#

我试图使如何在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。看来这似乎是最琐碎的事情,但是我完全坚持了下来。当我尝试使用“添加”功能进行相似的实验时,该函数进行了两次加倍操作并返回了一次加倍操作,我没有遇到任何问题。


阅读 319

收藏
2020-05-19

共1个答案

一尘不染

您不能std::string跨互操作边界传递C ++ 。您不能在C#代码中创建其中之一。因此,您的代码将永远无法工作。

您需要在互操作边界使用互操作友好类型。例如,以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");

在另一个方向上,您通常希望调用方分配缓冲区,被调用方可以在其中写入以下内容:

C ++

void foo(char *str, int len)
{
    // write no more than len characters into str
}

C#

[DllImport("...", CallingConvention = CallingConvention.Cdecl)
static extern void foo(StringBuilder str, int len);

....

StringBuilder sb = new StringBuilder(10);
foo(sb, sb.Capacity);
2020-05-19