2010-04-16 40 views
4

我需要从C#发送一个字符串到C++ WindowProc。与此有关的SO有许多相关的问题,但没有一个答案适用于我。这里的情况:C#发送消息到C++ WinProc

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++端的正确内存位置,但数据不在那里。我错过了什么?

回答

2

对于C++ LPWSTRLPSTR参数您需要在您的DllImport中使用C#StringBuilder

对于C++ LPCWSTRLPCSTR参数您需要在您的DllImport中使用C#string

+0

你能举个例子吗? – Nayan 2010-04-16 14:33:53

1

确保您的SendMessage调用以预期的同步方式进行,并且您的NativeMethods类映射正确的Win32调用(发送与PostMessage。)如果这不正确,可能您的邮件是在C++端进行处理,您已经离开了C#方法的范围,并且在堆栈上创建的任何局部变量都消失,导致您的指针变得糟糕。

跨线程调用的堆栈和堆注意事项:线程有自己的堆栈但共享堆。一个线程中堆栈分配的变量在另一个线程中不可见。字符串类型是.NET中的一个奇怪的鸭子。它是一个Object引发的引用类型,但在代码中看起来和感觉就像是一个值类型。所以也许传递一个指向堆分配数据的指针应该可以工作。这就是StringBuilder作为堆分配参考类型进来的地方。

+0

我肯定使用SendMessage,所以我不应该在处理完消息之前回到C#。 – jaws 2010-04-16 14:41:21

+0

这是一个跨线程调用?线程有自己的堆栈,但共享堆。一个线程中堆栈分配的变量在另一个线程中不可见。字符串类型是.NET中的一个奇怪的鸭子。它是Object派生的,引用类型,但看起来和感觉像是一个值类型。所以传递一个指向堆分配数据的指针应该可以工作。也许这就是StringBuilder进来的地方。 – 2010-04-16 14:52:53

+0

是的,它是跨线程的,它总是有意义的。 – jaws 2010-04-16 15:00:05