问题API与char *返回被IntPtr在P/invoke中捕获

问题描述:

我想P /调用一个C++ API返回一个char *,它是C#中的一个字符串。我知道这应该由IntPtr的捕获,然后将指针转换为使用封送像这样的字符串,问题API与char *返回被IntPtr在P/invoke中捕获

C++ API

char* WINAPI MY_API(const char *basebuf, char *strbuf) 
{ 
    return targetfunction(basebuf, strbuf); 
} 

C#的P/Invoke

[DllImport("myDll.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)] 
internal static extern IntPtr MY_API([MarshalAs(UnmanagedType.LPStr)] string basebuf, 
            [MarshalAs(UnmanagedType.LPArray), Out] byte[] strbuf); 

C#包装

public string MY_API_WRAPPER(string basebuf, out string strbuf) 
{ 
    byte[] strbufTemp = new byte[256]; 

    IntPtr ret = MY_API(basebuf, strbufTemp); 
    string retstr = Marshal.PtrToStringAnsi(ret); 
    strbuf = MyDataConverter.ByteToString(strbufTemp); 

    return retstr; 
} 

out参数字符串是OK的。但返回的字符串(从IntPtr转换)是垃圾。

我可以修改C ​​++ API以将char *分配给任务内存,然后将其释放到C#Wrapper中,但更改本机代码不是选项。如果在没有包装的情况下使用API​​,它也有内存泄漏的风险。

我想知道当API调用结束时指针发生了什么?

+0

如何返回值分配呢? –

+0

@DavidHeffernan“targetfunction”的返回值是指向basebuf元素的指针。像这样(char * ret =(char *)&basebuf [0]) –

+1

那不行了。这是一个由pinvoke封送器管理的临时缓冲区。非托管函数返回后无效。您需要手动编组basebuf。 –

感谢大卫,我能够解决我的问题。由于函数的返回值是指向basebuf参数的指针,因此函数返回时会获取垃圾值。

Basebuf应该是一个IntPtr而不是IntPtr返回的字符串,以便在调用后获得正确的值。所以它应该像这样P/Invoked。

C#的P/Invoke

[DllImport("myDll.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)] 
internal static extern IntPtr MY_API(IntPtr basebuf, 
            [MarshalAs(UnmanagedType.LPArray), Out] byte[] strbuf); 

C#包装

public string MY_API_WRAPPER(string basebuf, out string strbuf) 
{ 
    byte[] strbufTemp = new byte[256]; 
    IntPtr basebufPtr = Marshal.StringtoHGlobalAnsi(basebuf) 
    IntPtr ret = MY_API(basebufPtr , strbufTemp); 
    string retstr = Marshal.PtrToStringAnsi(ret); 
    strbuf = MyDataConverter.ByteToString(strbufTemp); 
    Marshal.FreeHGlobal(basebufPtr); 
    return retstr; 
}