P/Invoke 改变传递参数的值
Posted
技术标签:
【中文标题】P/Invoke 改变传递参数的值【英文标题】:P/Invoke changes the values of passed arguments 【发布时间】:2016-07-16 15:38:19 【问题描述】:所以我在 DLL 中有这个 c++ 函数
__declspec(dllexport) MOUSERAWDATA __stdcall GetMouseRawData(LPARAM lParam)
UINT bufferSize = 0;
BYTE *buffer = new BYTE[bufferSize];
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &bufferSize, sizeof(RAWINPUTHEADER));
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, (LPVOID)buffer, &bufferSize, sizeof(RAWINPUTHEADER));
RAWINPUT *raw = (RAWINPUT*)buffer;
MOUSERAWDATA data;
if (raw->header.dwType == RIM_TYPEMOUSE)
data.longX = raw->data.mouse.lLastX;
data.longY = raw->data.mouse.lLastY;
return data;
以下是在我的 c# 项目中:
[DllImport("RawInput.dll", CallingConvention = CallingConvention.StdCall)]
private static extern MouseRawData GetMouseRawData(IntPtr lParam);
.
.
.
protected override void WndProc(ref Message m)
switch(m.Msg)
case WM_CREATE:
if (AttachMouseListener(this.Handle))
Console.WriteLine("It works!");
break;
case WM_INPUT:
MouseRawData data = GetMouseRawData(m.LParam);
break;
default:
base.WndProc(ref m);
break;
当我运行这段代码时,以下值被传递给 GetMouseRawData
但由于某种原因,lParam 在 C++ 端的值总是不同的。
我本例 0x004fe95c = 5237084
有人知道为什么会这样吗?
【问题讨论】:
您的 pinvoke 声明与您的 C 函数不匹配。可能是因为 MouseRawData 声明,我们没有看到它的好处,返回结构的函数总是很棘手。改用 bool GetMouseRawData(LPARAM lParam, MOUSERAWDATA* data)。 【参考方案1】:您正在分配一个长度为 0 的缓冲区。然后“询问”缓冲区的大小。然后通过告诉他们您的缓冲区大小正确来欺骗 GetRawInputData。将缓冲区分配移动到第一次调用后您已了解所需缓冲区大小的位置。
UINT bufferSize = 0;
BYTE *buffer = new BYTE[bufferSize];
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &bufferSize, sizeof(RAWINPUTHEADER));
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, (LPVOID)buffer, &bufferSize, sizeof(RAWINPUTHEADER));
RAWINPUT *raw = (RAWINPUT*)buffer;
您需要delete[]
您的缓冲区以防止泄漏。
您需要初始化data
(MOUSERAWDATA) 以防止它有条件地包含垃圾。调用者如何知道raw->header.dwType == RIM_TYPEMOUSE
是真是假?
您是否考虑过根据Microsoft guidance 直接调用 GetRawInputData():
public static extern int GetRawInputData(IntPtr hRawInput, RawInputCommand uiCommand, out RAWINPUT pData, ref int pcbSize, int cbSizeHeader);
protected override void WndProc(ref Message m)
if (m.Msg == (int)WindowMessages.RawInput) // WindowMessages.RawInput = 0x00FF (WM_INPUT)
RAWINPUT input = new RAWINPUT();
int outSize = 0;
int size = Marshal.SizeOf(typeof(RAWINPUT));
outSize = Win32API.GetRawInputData(m.LParam, RawInputCommand.Input, out input, ref size, Marshal.SizeOf(typeof(RAWINPUTHEADER)));
if (outSize != -1)
if (input.Header.Type == RawInputType.Mouse)
//input.Mouse.LastX;
//input.Mouse.LastY;
base.WndProc(ref m);
【讨论】:
感谢您的意见。但是您的回答并没有告诉我为什么传递的值会发生变化。 你能确认你正在构建你的 .net 和你的 c++ 具有相同的位数吗? 64 位或 32 位。 IntPtr 将是不同的大小。以上是关于P/Invoke 改变传递参数的值的主要内容,如果未能解决你的问题,请参考以下文章