2

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?

4

2 回答 2

5

使用 aStringBuilder传递本机代码可以填充的字符数组(请参阅Fixed-Length String Buffers)。

声明函数:

[DllImport("FirstDll.dll", CharSet=CharSet.Ansi)]
public static extern int xmain(int argc, string argv, StringBuilder argv2);

用它:

// 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();
于 2012-06-01T21:08:58.173 回答
2

为 DLLImport 调用提供一些其他信息。看下面我自己的例子:

[DllImport("tcpipNexIbnk.dll", EntryPoint = "SendData", CallingConvention = CallingConvention.Cdecl)]
    public static extern int Send([MarshalAs(UnmanagedType.LPWStr)]string message);

注意两件事,CallingConvention 参数:CallingConvention = CallingConvention.Cdecl)

照原样使用它。

然后在 c# 字符串类型后面,您可以使用 MarshalAS 指令使用不同的非托管类型,这会将您的 C# 字符串参数转换为您在 c++ 程序中拥有的本机字符串类型:

public static extern int Send([MarshalAs(UnmanagedType.LPWStr)]string message);

希望能帮助到你。

于 2012-06-01T19:29:29.810 回答