如何在消息框中显示来自 C# 的带有 WCHAR* 的 C 函数

Posted

技术标签:

【中文标题】如何在消息框中显示来自 C# 的带有 WCHAR* 的 C 函数【英文标题】:how to display in messagebox a C function from C# with a WCHAR* 【发布时间】:2015-07-29 08:06:51 【问题描述】:

我正在构建一个加载 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() 获取一个字符串。

【问题讨论】:

等等... HWStr 超出范围时不会被销毁,因此 HWStr.c_str() 返回的指针无效? _Test_EchoString 返回一个整数 (public static extern int _Test_EchoString)。 int.ToString 返回数字的字符串表示形式 Stringwchar_t* Test_EchoString( wchar_t *InputStr ) 方法中是什么?是std::wstring吗? 【参考方案1】:

您的代码中有两个问题:

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

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

1)首先是在Heap中分配你想要返回的内存,然后通过另一个调用释放它:

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)HWStr仍然有效时,将回调传递给C方法并传递给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);

【讨论】:

感谢您的建议

以上是关于如何在消息框中显示来自 C# 的带有 WCHAR* 的 C 函数的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C# Winforms 程序的文本框中突出显示文本?

如何将 CEdit 类型的数据转换为 CString 类型的数据以及如何在消息框中显示? [复制]

如何从输入框中显示 HTML

C#:在自定义消息框中显示进度条变化

窗口消息框中的 C# WPF XAML

C#如何匹配两个列表框中的项目