我需要将一个字符串从C#发送到C ++ WindowProc。关于SO的一些相关问题与此相关,但没有一个答案对我有用。情况如下:
PInvoke:
[DllImport("user32", CharSet = CharSet.Auto)]
public extern static int SendMessage(IntPtr hWnd, uint wMsg, IntPtr wParam, string lParam);
C#:
string lparam = "abc";
NativeMethods.User32.SendMessage(handle, ConnectMsg, IntPtr.Zero, lparam);
C++:
API LRESULT CALLBACK HookProc (int code, WPARAM wParam, LPARAM lParam)
{
if (code >= 0)
{
CWPSTRUCT* cwp = (CWPSTRUCT*)lParam;
...
(LPWSTR)cwp->lParam <-- BadPtr
...
}
return ::CallNextHookEx(0, code, wParam, lParam);
}
我尝试了很多不同的东西,将字符串编组为LPStr,LPWStr,也尝试从非托管内存创建IntPtr,并使用Marshal.WriteByte写入。
指针是C ++端的正确内存位置,但数据不存在。我错过了什么?
答案 0 :(得分:2)
对于C ++ LPWSTR
或LPSTR
参数,您需要在DllImport中使用C#StringBuilder
。
对于C ++ LPCWSTR
或LPCSTR
参数,您需要在DllImport中使用C#string
。
答案 1 :(得分:1)
确保您的SendMessage调用以预期的同步方式进行,并且您的NativeMethods类映射正确的Win32调用(Send与PostMessage。)如果这不正确,则可能在您的邮件处理时在C ++端,您已经离开了C#方法的范围,并且在堆栈上创建的任何局部变量都消失了,导致您的指针错误。
跨线程调用的堆栈和堆注意事项:线程有自己的堆栈但共享堆。一个线程中的堆栈分配变量在另一个线程中不可见。字符串类型是.NET中的一个奇怪的鸭子。它是一个Object派生的引用类型,但在代码中看起来和感觉都像是一个值类型。所以也许传递一个指向堆分配数据的指针应该可行。这就是StringBuilder作为堆分配引用类型的地方。