0

I am trying to use my C++ class in my C# program. So I made a .dll-file to use it in C#. My problem is, that I am working with strings. My question is: How can I return a std::string to my C# program?

My C++ class (header-file):

using namespace std;

class CComPort
{
public:     
    string ReadLine();          
    void WriteLine(string userInput);
};

My dll code:

string CppWrapper::CComPortWrapper::ReadLineWrapper()
{
    return comPort->ReadLine();
}

void CppWrapper::CComPortWrapper::WriteLineWrapper(string userInput)
{
    comPort->WriteLine(userInput);
}

My C#-Code:

comPort.WriteLineWrapper(tb_send.Text);

Error:

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

I tried to change the dll file to something like this, but it didn't worked:

void CppWrapper::CComPortWrapper::WriteLineWrapper(String ^ userInput)
{
    comPort->WriteLine(userInput);
}

What is the rigth way to change it?

User987123
  • 97
  • 1
  • 11
  • 1
    Possible duplicate of [std::string in C#?](https://stackoverflow.com/questions/874551/stdstring-in-c) – user0042 Oct 31 '17 at 15:12
  • std::string is not supported by the C# language. We can't tell what type your ComPort::WriteLine() function needs, but Marshal::StringToHGlobalAnsi() tends to fit. Don't forget Marshal::FreeHGlobal(). Paying attention to the exact encoding never hurts either, consider declaring it `void WriteLine(array^ buffer);` and use `pin_ptr` so the C# code has a shot at getting it right with the Encoding class. – Hans Passant Oct 31 '17 at 15:28

1 Answers1

1

It appears that you're wrapping a class used just for serial port communication. There are ways of accessing the serial port directly from C#, without needing C++/CLI. Unless there's a lot of logic in the C++ class that cannot be ported/would be hard to port to C#, please do consider doing the serial communication in C#.


You haven't shown us the declaration of your CComPortWrapper class. I'm assuming that it's public ref class CComPortWrapper.

If the goal of your wrapper is to make it callable from managed languages (e.g., C#), then you should use managed types in your declaration.

In this case, you should declare the methods of CComPortWrapper to take & return System::String^. Within the wrapper, convert it to/from std::string, and call the unmanaged class with that.

I recommend using marshal_as to do the conversion, especially since you're converting from one class to another. You don't need to deal with explicitly allocating memory or anything like that; let each string class manage its own memory, and let marshal_as deal with copying & converting the data.

#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);
}
David Yaw
  • 27,383
  • 4
  • 60
  • 93
  • I am getting this error with your code: "'msclr::interop::error_reporting_helper<_To_Type,_From_Type,false>::marshal_as': This conversion is not supported by the library or the header file needed for this conversion is not included. Please refer to the documentation on 'How to: Extend the Marshaling Library' for adding your own marshaling method." – User987123 Oct 31 '17 at 15:45
  • And yes it is 'public ref class CComPortWrapper' – User987123 Oct 31 '17 at 15:49
  • @User987123 make sure you have the proper include. See edit. – David Yaw Oct 31 '17 at 15:57