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?

2
  • 1
    Possible duplicate of std::string in C#? Commented Oct 31, 2017 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<Byte>^ buffer); and use pin_ptr so the C# code has a shot at getting it right with the Encoding class. Commented Oct 31, 2017 at 15:28

1 Answer 1

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);
}
Sign up to request clarification or add additional context in comments.

3 Comments

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."
And yes it is 'public ref class CComPortWrapper'
@User987123 make sure you have the proper include. See edit.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.