在 C# 中使用带有字符串的 C++ 类 (Dll)

Posted

技术标签:

【中文标题】在 C# 中使用带有字符串的 C++ 类 (Dll)【英文标题】:Use C++ class in C# with strings (Dll) 【发布时间】:2017-10-31 15:07:44 【问题描述】:

我正在尝试在我的 C# 程序中使用我的 C++ 类。所以我制作了一个 .dll 文件以在 C# 中使用它。我的问题是,我正在使用字符串。我的问题是:如何将 std::string 返回到我的 C# 程序?

我的 C++ 类(头文件):

using namespace std;

class CComPort

public:     
    string ReadLine();          
    void WriteLine(string userInput);
;

我的 dll 代码:

string CppWrapper::CComPortWrapper::ReadLineWrapper()

    return comPort->ReadLine();


void CppWrapper::CComPortWrapper::WriteLineWrapper(string userInput)

    comPort->WriteLine(userInput);

我的 C#-代码:

comPort.WriteLineWrapper(tb_send.Text);

错误:

'CComPortWrapper.WriteLineWrapper(?,?)' is not supported by the language.

我尝试将 dll 文件更改为类似的内容,但没有成功:

void CppWrapper::CComPortWrapper::WriteLineWrapper(String ^ userInput)

    comPort->WriteLine(userInput);

改变它的正确方法是什么?

【问题讨论】:

std::string in C#?的可能重复 std::string 不受 C# 语言支持。我们无法判断您的 ComPort::WriteLine() 函数需要什么类型,但 Marshal::StringToHGlobalAnsi() 往往适合。不要忘记 Marshal::FreeHGlobal()。注意确切的编码也没有什么坏处,考虑将其声明为 void WriteLine(array<Byte>^ buffer); 并使用 pin_ptr 以便 C# 代码可以使用 Encoding 类正确处理。 【参考方案1】:

看来您正在包装一个仅用于串行端口通信的类。有一些方法可以直接从 C# 访问串行端口,而无需 C++/CLI。除非 C++ 类中有很多逻辑无法移植/难以移植到 C#,否则请考虑在 C# 中进行串行通信。


你还没有向我们展示你的CComPortWrapper 类的声明。我假设它是public ref class CComPortWrapper

如果您的包装器的目标是使其可从托管语言(例如 C#)中调用,那么您应该在声明中使用托管类型。

在这种情况下,您应该声明CComPortWrapper 的方法以获取并返回System::String^。在包装器中,将其转换为/从std::string,并用它调用非托管类。

我建议使用marshal_as 进行转换,尤其是因为您要从一个类转换到另一个类。您不需要处理显式分配内存或类似的事情;让每个字符串类管理自己的内存,让marshal_as处理数据的复制和转换。

#include <msclr\marshal_cppstd.h>

using namespace System;

String^ CppWrapper::CComPortWrapper::ReadLineWrapper()

    std::string result = comPort->ReadLine();
    return marshal_as<String^>(result);


void CppWrapper::CComPortWrapper::WriteLineWrapper(String^ userInput)

    std::string input = marshal_as<std::string>(userInput);
    comPort->WriteLine(input);

【讨论】:

您的代码出现此错误:“'msclr::interop::error_reporting_helper<_to_type>::marshal_as': 库或头文件不支持此转换不包括此转换所需的内容。请参阅有关“如何:扩展编组库”的文档以添加您自己的编组方法。” 是的,它是'public ref class CComPortWrapper' @User987123 确保您有正确的包含。见编辑。

以上是关于在 C# 中使用带有字符串的 C++ 类 (Dll)的主要内容,如果未能解决你的问题,请参考以下文章

如何在c#中使用C++ dll导出类[重复]

从 C++ 调用 C# dll(MSVC 编译器)

在 C++ DLL 和 C# 类之间来回传递变量

调用从 c# 返回 char* 的 c++ dll 函数。无法使用 DllImport()

创建 C++ Dll,并从 C# 调用它

将带有参数的 c# 回调方法传递给 c++ dll 会导致 System.ExecutionEngineException