传递从C#字符串到C ++ DLL和背部 - 小例子,

问题描述 投票:36回答:2

我试图做出如何的字符串传递到并从C ++ DLL在C#中的绝对简单的小例子。

我的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。这似乎是它证明是对付最琐碎的事情,但我完全被卡住就可以了。当我试图做类似的实验功能“添加”那花了两个双打和返回的双重我没有问题。

c# c++ pinvoke
2个回答
59
投票

你不能跨越互操作边界传递一个C ++ std::string。您不能创建那些在您的C#代码之一。所以,你的代码不能正常工作。

您需要在互操作界面使用互操作友好的类型。例如,空终止字符数组。当你分配和释放在同一个模块在存储效果很好。所以,从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);

0
投票

这是我喜欢最简单的方法 - 通过在一个字符串,并使用lambda获得响应

C#

 [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
 });

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");
     }
 } 
© www.soinside.com 2019 - 2024. All rights reserved.