来自 C# 的 C:字符串作为参数和 return 值?

C from C#: string as parameter and return value?

我在 Win32 DLL 的 .c 文件中调用 doThis 函数。

#include <stdio.h>

__declspec(dllexport) double doThis( char *message)
{
    printf("do nothing much");
    return 32.5;
}

使用此调用代码:

[DllImport(@"\vmware-host\Shared Folders\c-sharp\Hot\MusicIO\Debug\HelloWorld.dll", 
    CallingConvention=CallingConvention.Cdecl)]
public static extern double doThis(string message);


private void button1_Click(object sender, EventArgs e)
{
    double returned = doThis("what 2");
    MessageBox.Show("Click " + returned);
}

工作正常,但我希望函数 return char *... 和 return message 变量。

当我将 doThis 更改为 return 和 char * 并且调用代码期望 string 时,Win32 主机在运行时崩溃。

有什么建议吗?

[奇怪的是,我想我之前有这个工作]

让我们假设这个签名工作了一段时间:

__declspec(dllexport) char* doThis(char* message)

你从 C# 调用它,然后你有一个 char*。你把它复制到 string,然后……然后 什么? 你用那个 char* 做什么?

你打电话给 free 吗? 哪个free C运行时库?或者你不应该因为指针可能来自静态内存?你不知道,.NET mashaller 也不知道。


处理这个问题的正确方法是传递第二个 char* 参数,它指向某个缓冲区 you 已分配,并且 you负责释放。

好吧,在 C# 中并不一定要 。编组器可以为您处理。

所以定义一个这样的签名:

__declspec(dllexport) double doThis(char* message, char* output, int maxOutputLength)

maxOutputLength参数是一种安全措施,让你的C代码知道消息的最大长度。在您的 C 代码中按照您认为合适的方式使用它。

注意:在 C++ 代码中,message 将是 const char*,而 output 将仍然是 char*


在 C# 端,签名将涉及 StringBuilder:

[DllImport(@"HelloWorld.dll", CallingConvention=CallingConvention.Cdecl)]
public static extern double doThis(string message, StringBuilder output, int maxOutputLength);

然后,您分配一个具有一些初始容量的 StringBuilder,并传递给它:

var output = new StringBuilder(1024);
double returned = doThis("what 2", output, output.Capacity);
var outputStr = output.ToString();

编组人员会为您处理管道。