C函数的C#pinvoke返回char *

时间:2014-12-13 21:23:20

标签: c# c pinvoke marshalling

这就是我提出的:

非托管功能:

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

调用函数:

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();  
    }
}

结果:一堆胡言乱语

好的,感谢一些用户的帮助和更多的挖掘,这就是我最终做的事情:

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;

}

}

和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();  
    }

}

1 个答案:

答案 0 :(得分:2)

您不能返回指向局部变量的指针,因为它们是在堆栈上分配的(当函数返回时堆栈可能会被销毁)。

你需要在堆上分配内存(最好使用CoTaskMemAlloc,这样CLR可以在以后释放内存),并返回指向该内存的指针。

作为旁注,您可以在编组时直接返回string(假设它是一个以c结尾的unicode字符串),不需要返回IntPtr

此处有更多信息:http://limbioliong.wordpress.com/2011/06/16/returning-strings-from-a-c-api/