views:

53

answers:

1

I am calling a C# method from C code.

The C# method:

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

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

The C method:

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!
}

But if I use String instead of StringBuilder as below in my C# method declaration, f(p) and f(msg) both work. Why?

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

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

Note

the calling logic is like this:

c_method()---->delegate p_func--->callback()

not the reverse.

I checked the arg in the callback(StringBuilder arg), the Length, MaxCapacity, Capacity are all the same for char *p or msg[]. Only that *p leads to the exception. Why?

+1  A: 

When you use String as the parameter type, the CLR will not attempt to write any changes back to the native memory buffer. When you use a StringBuilder (which is the right choice for in/out string parameters), it will. But the memory p points to will be read-only because of the way you declared it, that's why yout get an error.

Mattias S
Thanks Mattias. Why char* p makes the memory read-only?
smwikipedia
http://stackoverflow.com/questions/2589949/c-string-literals-where-do-they-gohttp://stackoverflow.com/questions/349025/is-a-string-literal-in-c-created-in-static-memory
Mattias S