Passing String from Native C++ DLL to C# App
Solution 1
Use a StringBuilder
to pass a character array that native code can fill in (see Fixed-Length String Buffers).
Declare the function:
[DllImport("FirstDll.dll", CharSet=CharSet.Ansi)]
public static extern int xmain(int argc, string argv, StringBuilder argv2);
Use it:
// allocate a StringBuilder with enough space; if it is too small,
// the native code will corrupt memory
StringBuilder sb = new StringBuilder(4096);
xmain(2, @"C:\hhh.bmp", sb);
string argv2 = sb.ToString();
Solution 2
Give some other information to the DLLImport call. Look at the following example of my own:
[DllImport("tcpipNexIbnk.dll", EntryPoint = "SendData", CallingConvention = CallingConvention.Cdecl)]
public static extern int Send([MarshalAs(UnmanagedType.LPWStr)]string message);
Notice two things, the CallingConvention parameter: CallingConvention = CallingConvention.Cdecl)
Use that as it is.
And then just behind the c# string type, you can play with the different Unmanaged types using the MarshalAS instruction, that will cast your C# string parameter to the native string type you have in your c++ program:
public static extern int Send([MarshalAs(UnmanagedType.LPWStr)]string message);
Hope it helps.
Jacob Quisenberry
I am a Software Engineer at ACT Litigation Services.
Updated on June 04, 2022Comments
-
Jacob Quisenberry almost 2 years
I have written a DLL in C++. One of the functions writes to a character array.
C++ Function
EXPORT int xmain(int argc, char argv[], char argv2[]) { char pTypeName[4096]; ... //Other pTypeName ends up populated with "Portable Network Graphics" //This code verifies that pTypeName is populated with what I think it is: char szBuff[64]; sprintf(szBuff, pTypeName, 0); MessageBoxA(NULL, szBuff, szBuff, MB_OK); //The caption and title are "Portable Network Graphics" ... //Here, I attempt to copy the value in pTypeName to parameter 3. sprintf(argv2, szBuff, 0); return ret; }
C# Import
//I believe I have to use CharSet.Ansi because by the C++ code uses char[], [DllImport("FirstDll.dll", CharSet=CharSet.Ansi)] public static extern int xmain(int argc, string argv, ref string zzz);
C# Function
private void button2_Click(object sender, EventArgs e) { string zzz = ""; int xxx = xmain(2, @"C:\hhh.bmp", ref zzz); MessageBox.Show(zzz); //The message box displays //MessageBox.Show displays "IstuÈst¼ÓstÄstlÄstwÄstiÑstõÖstwÍst\ // aÖst[ÖstÃÏst¯ÄstÐstòÄstŽÐstÅstpÅstOleMainThreadWndClass" }
I have attempted to pass a parameter from C# by reference and have the C++ DLL populate the parameter. Even though I have verified that the value is correct in the DLL, gibberish gets passed to the C# application.
What can I do to write the correct string value to the C# string?