如何在 C++ 和 C# 之间传递字符串参数?

Posted

技术标签:

【中文标题】如何在 C++ 和 C# 之间传递字符串参数?【英文标题】:How to pass string parameters between C++ and C#? 【发布时间】:2015-01-21 07:23:17 【问题描述】:

我在我的 C# 项目中导入了一个 C++ 库。我可以得到一个没有参数的 C++ 方法的答案。我想要做的是将一些字符串参数发送到 C++ 并得到它的结果。

在 C++ 中:

public String SomeMethod(String param1, String param2)

     //Some code


在 C# 中:

[DllImport("Library Path")]
public static extern string SomeMethod(string param1, string param2);

我该怎么做?

【问题讨论】:

你的意思是 C++ Library 的意思是“C++ ATL 库”吗? 使用C++/CLI构建一个包装类 【参考方案1】:

对于从 C# 传递到 C++ 的 输入参数 的字符串,您可以在 C++ 端的接口处使用 LPCWSTR(即const wchar_t*),并使用 进行编组UnmanagedType.LPWstr C# 端的选项。

但是当你想将字符串从 C++ 返回到 C#时,你必须注意。 事实上,字符串必须以某种方式在 C++ 中分配,然后必须将字符串指针传递给 C#。当不再需要该字符串时,C# 和 CLR 必须能够正确释放,而这一点可能会出现问题。例如:C#/CLR 应该能够使用 C++ 代码用于分配字符串的 same 分配器来释放字符串内存。

可以使用 BSTRs 解决对在 C++ 中创建并在 C# 中使用的字符串使用相同内存分配器的问题。BSTR 是一个 COM 字符串,它是使用 COM 分配器分配的,并且可以使用 same COM 分配器来释放。因此,C++ 端和 C# 端都可以为字符串共享同一个内存分配器。

要返回 BSTR,您可以使用 MarshalAs.UnmanagedTypeBStr 选项。

有关 C# 中的字符串编组的更多详细信息,请参阅 this MSDN page。

C++中:

//
// Note: Export using a pure C interface from C++ DLL.
// (You can use C++ *inside* the DLL boundaries.)
// __stdcall is a widely used calling convention for 
// C DLL functions (e.g. lots of Win32 APIs use it).
//
extern "C" BSTR __stdcall GetSomeString(void)

    //
    // Note: BSTRs are allocated using SysAllocString()
    // (...and freed using SysFreeString()).
    //
    // You could also use a convenient ATL RAII wrapper
    // (instead of using raw BSTRs inside C++ code), 
    // like CComBSTR.
    //
    return ::SysAllocString(L"Hello from C++!");

C#中:

[DllImport(@"YourDll.dll", CallingConvention = CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.BStr)]
private static extern string GetSomeString();

如果您选择将BSTRs 作为返回字符串,对于C++ 函数接口代码的连贯性,您可能还希望使用BSTRs 作为输入 字符串(即使这不是绝对必要的)。


另一个选项是请求调用者提供一个适当大小的缓冲区,本机 C++ 函数将用返回的字符串填充该缓冲区。这有点类似于几个 Win32 API(例如 GetWindowText())所做的。 举个例子,here你可以找到GetWindwoText()对应的P/Invoke:

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);

但是,我认为从 C# 调用的角度来看,返回 BSTR 会更好(事实上,例如,在 C# 端,您不需要使用 StringBuilder 作为输出字符串等)。


最后但并非最不重要的一点是,您可能感兴趣的另一个选项是构建一个小型 C++/CLI 桥接层,以将您的本机 C++ 代码公开给 C#,并在本机和托管之间使用C++/CLI(例如 System::String 类)。

【讨论】:

以上是关于如何在 C++ 和 C# 之间传递字符串参数?的主要内容,如果未能解决你的问题,请参考以下文章

从 C++ 传递函数指针以由 C# 调用 - 函数参数包括宽字符字符串 (LPCWSTR)

将 C# 字符串传递给 C++,并将 C++ 结果(字符串、char*.. 任何)传递给 C#

C# 调用C++ DLL,而c++函数的有一个参数需要是null,该怎么传递?

如何通过 emscripten 在 C++ 和 javascript 之间传递字符串

如何使用 DLLImport 将字符串从 C# 传递到 C++(以及从 C++ 到 C#)?

C++ 将字符串传递到 C# dll