如何在 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 分配器来释放字符串内存。
可以使用 BSTR
s 解决对在 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();
如果您选择将BSTR
s 作为返回字符串,对于C++ 函数接口代码的连贯性,您可能还希望使用BSTR
s 作为输入 字符串(即使这不是绝对必要的)。
另一个选项是请求调用者提供一个适当大小的缓冲区,本机 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 之间传递字符串