Search code examples
c#c++pinvokedllimportdllexport

When calling an exported class of a C++ DLL by C#, C-style string members of the class are OK in one exported function, but not in the other


C++ console calls DLL OK, but not C#.

In the exported function setInputs , the const char*-type public member of class object is set OK, but in the exported function run, it becomes some meaningless characters.

exported DLL:

namespace{
    CLASS*CLASS_Ptr_Object=new CLASS();
    }

extern "C" __declspec(dllexport)
void setInputs(char*char_Ptr_Model,int int_Type){
        CLASS_Ptr_Object->m_char_Ptr_Input_Model=char_Ptr_Model;//when I print the public member m_char_Ptr_Input_Model, I see it is OK here
        CLASS_Ptr_Object->m_int_Type=int_Type;//int and double types are always OK
}

extern "C" __declspec(dllexport)
void run(){
    CLASS_Ptr_Object->run();//when I print the public member m_char_Ptr_Input_Model, I observe it has become some meaningless characters, although it was OK in previous exported function
}

how the public member is defined in header file:

class CLASS
    {

    //...

    public:
        const char*m_char_Ptr_Input_Model;
    };

Invoke in C#:

[DllImport(@"DLL.dll", EntryPoint = "setInputs")]
        public static extern setInputs(
            [In, Out, MarshalAs(UnmanagedType.LPStr)]string char_Ptr_Model
            , [In, Out, MarshalAs(UnmanagedType.I4)]int int_Type
             );

 [DllImport(@"DLL.dll", EntryPoint = "run")]
 public static extern run();

Solution

  • The content of the character buffer that supplied by the C# marshaller is only valid for the duration of the call to setInputs. As soon as setInputs finishes, referring to that buffer is invalid.

    The marshaller creates a temporary buffer to hold the character array, converts from the UTF-16 .net string to an 8 bit string. And then calls setInputs passing the address of the temporary buffer. When setInputs returns, the temporary buffer is destroyed. But you've held on to the address of that buffer and now you have a pointer to who knows what.

    You will need to take a copy of the string. The simplest way is to declare the member to be of type std::string and use the assignment operator that accepts a const char* assignment source.