P / Invoke,C#将字符串返回给本机代码

时间:2013-01-10 08:25:57

标签: pinvoke

我的代码有效,但我害怕P / Invoke中的内存。

这是我将从本机C ++代码调用的委托。

[UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode)]
public delegate string CommandCallbackDelegate([MarshalAs(UnmanagedType.LPWStr)] string command
    , [MarshalAs(UnmanagedType.LPWStr)] string arg1
    , [MarshalAs(UnmanagedType.LPWStr)] string arg2
    );

在C#中,我将委托传递给本机DLL。

private static GCHandle _gcHandle;
public static void RegisterCommandCallback(CommandCallbackDelegate fun) { _gcHandle = GCHandle.Alloc(fun);

    if (IntPtr.Size == 8)
        RegisterCommandCallback_x64(fun);
    else
        RegisterCommandCallback_x86(fun);
}

在本机DLL中,在我获得函数指针后,我可以成功调用该方法并从C#中获取返回的String

typedef LPCWSTR (WINAPI* PFN_CommandCallback)( LPCWSTR wszCommand, LPCWSTR wszArg1, LPCWSTR wszArg2);
PFN_CommandCallback g_pfnCommandCallback = ....;

LPCWSTR wszRet = g_pfnCommandCallback( L"CMD", L"ARG1", L"ARG2");

正如您所看到的,C#方法将String返回到本机DLL,我不确定返回的非托管内存是否由GC充满。

虽然上面的代码有效,但我担心它正在访问刚刚发布的内存。

1 个答案:

答案 0 :(得分:1)

在这种情况下,pinvoke marshaller使用共享COM分配器分配字符串返回值。因此,您的本机代码应该在本机DLL返回的指针上调用CoTaskMemFree。因此,在释放内存之前,您可能需要复制内容!

顺便说一句,没有必要用[MarshalAs(UnmanagedType.LPWStr)]来装饰参数,因为这只是重新声明了默认值。删除后,您的代码将更容易阅读。