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

asu*_*and 38 c# c++ pinvoke

我试图制作绝对最简单的最小例子,说明如何在C#中向C++ DLL传递字符串.

我的C++看起来像这样:

using std::string;

extern "C" {
    string concat(string a, string b){
        return a + b;
    }
}
Run Code Online (Sandbox Code Playgroud)

像标题一样

using std::string;

extern "C" {
    // Returns a + b
    __declspec(dllexport) string concat(string a, string b);
}
Run Code Online (Sandbox Code Playgroud)

我的C#是

[DllImport("*****.dll", CallingConvention = CallingConvention.Cdecl)]
    static extern string concat(string a, string b);
}
Run Code Online (Sandbox Code Playgroud)

我用它来调用它:Console.WriteLine(concat("a","b"));

但是这会产生System.AccessViolationException.这似乎是处理最琐碎的事情,但我完全坚持下去.当我尝试使用"添加"功能进行类似的实验,这个功能需要两个双打并且返回一个双重而没有问题.

Dav*_*nan 60

您不能std::string跨互操作边界传递C++ .您无法在C#代码中创建其中一个.所以你的代码永远不会工作.

您需要在互操作边界使用互操作友好类型.例如,以null结尾的字符数组.当您在同一模块中分配和释放内存时,这很有效.因此,将数据从C#传递到C++时很简单.

C++

void foo(const char *str)
{
    // do something with str
}
Run Code Online (Sandbox Code Playgroud)

C#

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

....

foo("bar");
Run Code Online (Sandbox Code Playgroud)

在另一个方向,您通常希望调用者分配缓冲区,被调用者可以写入:

C++

void foo(char *str, int len)
{
    // write no more than len characters into str
}
Run Code Online (Sandbox Code Playgroud)

C#

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

....

StringBuilder sb = new StringBuilder(10);
foo(sb, sb.Capacity);
Run Code Online (Sandbox Code Playgroud)

  • @orion谢谢.通常你会用一个功能来做.size参数将是ref int.将null传递给SB表示您想知道长度.然后再打电话. (2认同)
  • 如何返回字符串作为返回值而不是输出参数? (2认同)

Jon*_*nny 10

这是我喜欢的最简单的方法 - 传入一个字符串,并使用 lambda 来获取响应

C#

 public delegate void ResponseDelegate(string s);

 [DllImport(@"MyDLL.dll", EntryPoint ="Foo", CallingConvention = CallingConvention.StdCall)]
 public static extern void Foo(string str, ResponseDelegate response);
 ...
 
 Foo("Input", s =>
 {
    // response is returned in s - do what you want with it
 });
Run Code Online (Sandbox Code Playgroud)

C++

 typedef void(_stdcall *LPEXTFUNCRESPOND) (LPCSTR s);

 extern "C"
 {
     __declspec(dllexport) void __stdcall Foo(const char *str, LPEXTFUNCRESPOND respond) 
     {
         // Input is in str
         // Put your response in respond()
         respond("HELLO");
     }
 } 
Run Code Online (Sandbox Code Playgroud)

  • 这真的很不寻常,但也非常可爱! (5认同)
  • 您能解释一下这个例子中的 ResponseDelegate 是什么吗? (2认同)