C来自C#:string作为参数和返回值?

时间:2015-09-14 19:49:57

标签: c# .net c interop

我在Win32 DLL的<div id="navPlaceHolder"></div> //css #navPlaceHolder{ height:50px; visibility:hidden; } 文件中调用doThis函数。

.c

使用此调用代码:

#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); } ...并返回char *变量。

当我更改message以返回doThis,并且调用代码期望char *时,Win32主机在运行时崩溃。

有什么建议吗?

[奇怪的是,我认为我之前就已经开始工作了]

1 个答案:

答案 0 :(得分:2)

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

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

你从C#调用它然后你有一个char*。你将它复制到string,然后......然后什么?你对char*做了什么?

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

处理此问题的正确方法是传递第二个char*参数,该参数指向您分配的某个缓冲区,负责释放。

好吧,在C#中,实际上并不是。编组员可以为你处理这个问题。

所以定义这样的签名:

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

maxOutputLength参数是一种安全措施,让您的C代码知道消息的最大长度。根据您的C代码使用它。

注意:在C ++代码中,messageconst 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();

marshaller为你处理管道。