如何使用 WCHAR* 在消息框中显示来自 C# 的 C 函数
how to display in messagebox a C function from C# with a WCHAR*
我正在构建一个加载 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()
中获取一个字符串。
您的代码中有两个问题:
在你的 C# 中你定义 _Test_EchoString
为 public static extern int _Test_EchoString
,所以当你执行它时,returned 值将是字符串 [=16] 的第一个字符的地址=].
在这里它显示了另一个问题,正如安德拉斯所说,你正在 returning 一个无效的指针,因为 HWStr.c_str()
returns 指向 std::wstring
对象的当前值的指针,所以只要 wstring
有效,它就有效,所以当方法 Test_EchoString
结束执行时,它不再有效(因为 HWStr
被销毁)。
有多种方法可以解决此问题,我将向您展示其中两种:
1) 首先是在堆中分配你想要return的内存,稍后再调用释放它:
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'[=10=]';
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);
}
我正在构建一个加载 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()
中获取一个字符串。
您的代码中有两个问题:
在你的 C# 中你定义 _Test_EchoString
为 public static extern int _Test_EchoString
,所以当你执行它时,returned 值将是字符串 [=16] 的第一个字符的地址=].
在这里它显示了另一个问题,正如安德拉斯所说,你正在 returning 一个无效的指针,因为 HWStr.c_str()
returns 指向 std::wstring
对象的当前值的指针,所以只要 wstring
有效,它就有效,所以当方法 Test_EchoString
结束执行时,它不再有效(因为 HWStr
被销毁)。
有多种方法可以解决此问题,我将向您展示其中两种:
1) 首先是在堆中分配你想要return的内存,稍后再调用释放它:
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'[=10=]';
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);
}