c# - 使用 P/Invoke 获取字符串

标签 c# c pinvoke

我有一个包含两个项目的解决方案:一个 C# 控制台应用程序和一个 C 库。 C 库有一个返回 HRESULT 的函数。我需要以某种方式更改此函数以使其向我的 C# 代码返回一个字符串。它应该是这样的:

C#:

[DllImport("MyLib.dll", SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern long MyFunction(bunch of params, [MarshalAs(UnmanagedType.BStr)] out string text);

C:

extern "C" HRESULT __declspec(dllexport) MyFunction(bunch of params, BSTR* text)
{
PWSTR finalResult;
//lots of code

(*text) = SysAllocString(finalResult);
//cleanup code
}

我可以更改这两个项目。但是,无法知道字符串的大小。因此,我尝试在 C 库中分配字符串,但这会导致访问冲突异常和各种问题。解决这个问题的最佳方法是什么?

最佳答案

哇!将近 3 年了,这个问题没有正确的答案!

至少根据我的经验,从非托管中传输字符串的正确方法是将 StringBuilder 类与表示“缓冲区”.

像这样:

// C#

[DllImport("MyLib.dll",
    SetLastError = true,
    CharSet = CharSet.Auto,
    CallingConvention = CallingConvention.Cdecl)]
public static extern bool MyFunction(
    // other parameters,
    StringBuilder buffer,
    [MarshalAs(UnmanagedType.U4)] int bufferSize
);

// C:

extern "C" __declspec(dllexport) BOOL MyFunction(bunch of params, LPTSTR* text, unsigned int textSize)
{
    char *mySourceString = doSomethingAndReturnString(bunch of params);

    if ( textSize < strlen(mySourceString)) {
        SetLastError(ERROR_INSUFFICIENT_BUFFER)
        return FALSE;
    }

    strncpy(text, mySourceString, strlen(mySourceString))

    return TRUE;
}

并以这种方式使用它:

StringBuilder sb = new StringBuilder(128);
while (!NativeMethods.MyFunction(/*other parameters*/, sb, sb.Capacity))
{
    if (Marshal.GetLastWin32Error() != 0x7A) {
        // throw 
    }

    // Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER
    sb.Capacity *= 2;
}

关于c# - 使用 P/Invoke 获取字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8126662/

相关文章:

c# - 如何在不使用 Invoke 方法的情况下组合两个 lambda 表达式?

c# - 达到上传文件的最大长度

c - 如何在 C 语言中对性能优化进行单元测试?

c# - 如何在 Win7 中断开蓝牙设备与 C# .Net 的连接

c# - 在 asp.net mvc 项目中路由遗留的 asp.net 链接

c# - Dnlib - 从加载的程序集中执行 IL MethodBody

c - 为什么在下面的for循环中没有任何条件检查?

c - 基于隐式矢量化的 HPC 编程语言

c# - CoTaskMemAlloc v malloc v AllocHGlobal

c# - 将断言输出从 dll 重定向到文件