如何用WCHAR*在消息框中显示c#中的C函数

本文关键字:显示 中的 函数 WCHAR 何用 消息 | 更新日期: 2023-09-27 18:05:29

我正在构建一个加载c++库的c#应用程序。我从那个c++ DLL调用函数。我使用下面的函数来显示输入的字符串。

c++ dll:

wchar_t* Test_EchoString( wchar_t *InputStr )
{
String HWStr = String( InputStr );  
return HWStr.c_str();
}
c#代码:

[DllImport("testDll.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public static extern int  _Test_EchoString([MarshalAs(UnmanagedType.LPWStr)] string s);
private void echo_string_Click(object sender, RoutedEventArgs e)
{
    string upn = "aaaaa";
    _Test_EchoString(upn);
    MessageBox.Show(_Test_EchoString(upn).ToString());    
}

我得到消息框号码18666252,但我想从_Test_EchoString()得到一个字符串。

如何用WCHAR*在消息框中显示c#中的C函数

你的代码中有两个问题:

在c#中,您将_Test_EchoString定义为public static extern int _Test_EchoString,因此当您执行它时,返回值将是字符串HWStr.c_str()的第一个字符的地址。这里它显示了另一个问题,正如anderas所说,您正在返回一个无效的指针,因为HWStr.c_str()返回指向std::wstring对象的当前值的指针,因此只要wstring有效,它就有效,因此当方法Test_EchoString结束其执行时,它就不再有效(因为HWStr被销毁)。

有不同的方法来解决这个问题,我将向您展示其中的两种:

1)第一个是分配你想在堆中返回的内存,并在以后的另一个调用中释放它:

static wchar_t *Test_EchoStringResult;
extern "C" __declspec(dllexport) const wchar_t * Test_EchoStringNew(const wchar_t *InputStr)
{
    std::wstring HWStr(InputStr);
    HWStr += L" something";
    Test_EchoStringResult = new wchar_t[HWStr.length() + sizeof(wchar_t)];
    HWStr.copy(Test_EchoStringResult, HWStr.length());
    Test_EchoStringResult[HWStr.length()] = L''0';
    return Test_EchoStringResult;
}
extern "C" __declspec(dllexport) void Test_EchoStringDelete()
{
    delete[] Test_EchoStringResult;
}

在c#中的用法是:

[DllImport("testDll.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public static extern IntPtr Test_EchoStringNew(string foo);
[DllImport("testDll.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public static extern void Test_EchoStringDelete();
public void foo()
{
    string result = Marshal.PtrToStringAuto(Test_EchoStringNew("test"));
    MessageBox.Show(result.ToString());
    Test_EchoStringDelete();
}

对我来说,这看起来很丑,所以我更喜欢使用另一个模式

2)向C方法传递回调,并在HWStr仍然有效时将HWStr.c_str()传递给该方法:

extern "C" __declspec(dllexport) void Test_EchoString(const wchar_t *InputStr, void (*callback)(const wchar_t*))
{
    std::wstring HWStr(InputStr);
    HWStr += L" something";
    callback(HWStr.c_str());
}
下面是c#的用法:
[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public delegate void myCallback(string toShow);
[DllImport("testDll.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public static extern void Test_EchoString(string foo, myCallback callback);
public void foo()
{
    Test_EchoString("test", callback);
}
void callback(string toShow)
{
    MessageBox.Show(toShow);
}