C# pinvoke of C 函数返回 char*



这就是我想出的:

非托管函数:

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

}

您无法返回指向局部变量的指针,因为这些指针是在堆栈上分配的(并且当函数返回时堆栈可能会被销毁)。

您需要在 C 函数的堆上分配内存(最好使用 CoTaskMemAlloc以便 CLR 稍后可以释放内存),并返回指向该内存的指针。

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

更多信息在这里: http://limbioliong.wordpress.com/2011/06/16/returning-strings-from-a-c-api/

最新更新