Search code examples
c#cpinvokemarshalling

C# pinvoke of C function returning char*


This is what I came up with:

The unmanaged function:

extern  "C" __declspec(dllexport) char* callme(const char * sing) {
    char buf[10];
    sprintf(buf,"hey %s",sing);
    return buf;
}

The calling function:

class Program
{

    [DllImport("testnonclr.dll", CharSet = CharSet.Auto, CallingConvention =
        CallingConvention.Cdecl)]
    public static extern IntPtr callme([In,MarshalAs(UnmanagedType.LPStr)]
        string sing);

    static void Main(string[] args) {
        Console.Write( Marshal.PtrToStringAuto (callme("baby")  ));
        Console.ReadLine();  
    }
}

The result: a bunch of gibberish

Ok, thanks to the help of some users and more digging, this is what I ended up doing:

extern  "C" {
 __declspec(dllexport)  char* __stdcall callme(const char * sing)
{
static char *buf=NULL;
    char fubb[10];


sprintf(fubb,"hey %s",sing);
ULONG usize=strlen(fubb)+sizeof(char);
buf=(char *)::GlobalAlloc (GMEM_FIXED,usize);


strcpy(buf,fubb);

return buf;

}

}

and C#:

class Program
{

    [DllImport("testnonclr.dll", CharSet = CharSet.Unicode, CallingConvention =    C  
    CallingConvention.StdCall )]
   [return: MarshalAs(UnmanagedType.LPStr)]
    public static extern string callme([In, MarshalAs(UnmanagedType.LPStr)] string sing);
    static void Main(string[] args)
    {
        string rrr = callme("baby"); 
        Console.WriteLine(rrr); 


        Console.ReadLine();  
    }

}


Solution

  • You cannot return a pointer to a local variable since those are allocated on the stack (and the stack may get destroyed when the function returns).

    You'd need to allocate memory on the heap (preferably using CoTaskMemAlloc so the CLR can free up the memory later) on your C function and return a pointer to that memory.

    As a side note, you can directly return a string when marshalling (assuming it's a c null-terminated unicode string), no need to return IntPtr.

    More info here: http://limbioliong.wordpress.com/2011/06/16/returning-strings-from-a-c-api/