关于StringBuilder的互操作问题

时间:2010-08-18 09:29:38

标签: c# .net interop marshalling managed

我从C代码调用C#方法。

C#方法:

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate void p_func(StringBuilder arg);

    public static void callback(StringBuilder arg)
    {
        Console.WriteLine(arg.ToString());
    }

C方法:

extern "C" void  c_method(p_func f)
{
 char msg[4];
 ::strcpy(msg,"123");
 char* p="123"; 
 f(msg); // this is ok
    f(p);   //Error: Attempted to read or write protected memory!
}

但是如果我在C#方法声明中使用String而不是StringBuilder,则f(p)和f(msg)都可以工作。为什么呢?

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate void p_func(String arg);

    public static void callback(String arg)
    {
        Console.WriteLine(arg.ToString());
    }

注意

调用逻辑是这样的:

c_method()---->委托p_func --->回调()

不是相反的。

我检查了回调(StringBuilder arg)中的 arg Length,MaxCapacity,Capacity 对于char * p都是一样的或者msg []。只有* p导致异常。为什么呢?

1 个答案:

答案 0 :(得分:1)

当您使用String作为参数类型时,CLR将不会尝试将任何更改写回本机内存缓冲区。当你使用StringBuilder(它是输入/输出字符串参数的正确选择)时,它会。但是内存p指向的只是因为你声明它的方式是只读的,这就是你得到错误的原因。