在.NET如何定义整块内存空间

来源:百度知道 编辑:UC知道 时间:2024/06/04 05:17:57
如题,在API编程中经常有指针类型的函数声明,对应于.net是引用long类型,可是在对这个数组进行访问的时候由于CLR是堆分配的,其地址并不是连续的。结果没办法访问所有元素。
正如本例子:
Private Declare Function StartMaskKey Lib "MaskKey.dll" (ByRef lpdwVirtualKey As Long, ByVal nLength As Long, Optional ByVal bDisableKeyboard As Boolean = False) As Long

Dim key() As Long = {Keys.LWin, Keys.A, Keys.G, Keys.RWin}

StartMaskKey(key(0), 4)
这个网上流传的屏蔽键盘的HOOKDLL,本意是屏蔽key()数组的所有键,可是由于堆分配的不连续性只能屏蔽头两个,可是在VC++和VB都是正确的!!

希望有能能给出不修改DLL的解决方案,谢谢各位
to funlove9 :
这个就是吃掉键盘消息的DLL,源代码我也有,这里的问题是怎样在.NET定义整块内存空间,毕竟MS的DLL不是我能轻易改的。
to
StartMaskKey(key,4)无效,注意我的定义是long类型,这个语句本身是没有问题的,问题在于.NET对数组使用堆分配导致的内存空间不连续。
to ychs55
unsafe就没意义了,而且VB.NET也没有unsafe,我只是要一种整块内存的分配方法,应该用这种开关才对……
to funlove9
栈我试过了,更惨,只能一个,后来查了下栈在.net也是用堆的
to all
我只是想知道一个明确的回答,有或者没有,如果有怎么实现,如果没有有什么VB.NET和C#通用的替代方案
大家go on

这的了解托管到非托管数据传递,你在c#里声明DLL形式直接关系到参数传递的方式,VB使用ByRef,C#使用ref传递的lpdwVirtualKey数组,传递方式是把托管内存内数据COPY到程序的非托管内存堆上,然后把非托管的地址上的数据给外部DLL使用,使用完成后COPY回托管内存,使用key(0)只是传递了一个LONGLONG 64位元素,所以只有两个有效,正确的应该传递数组KEY出去,声明的时候VB使用ByVal lpdwVirtualKey() As Integer,C#使用int[] lpdwVirtualKey声明,传递直接使用StartMaskKey(key,4),这样的传递到非托管效果和richardbao2000 提到的C# 中的 unsafe fixed 钉住内存效果是一样的,只是这个操作由.net框架完成了而已,这样的数据传递效果是,先把key内存空间钉住,CLR不会释放或移动它,然后把托管内存地址直接传递给外部DLL直接使用,效率更高.

也就是说你声明DLL时直接这样定义就能满足你的要求
VB:
Private Declare Function StartMaskKey Lib "MaskKey.dll" (ByVal lpdwVirtualKey() As Integer, ByVal nLength As Integer, Optional ByVal bDisableKeyboard As Boolean = False) As Integer
C#:
using System.Runtime.InteropServices;

[DllImport("MaskKey.dll"]
public static extern int StartMaskKey (int[] lpdwVirtualKey, int nLength,bool bDisableKeyboard );

使用
vb
DIM key(...) as integer
StartMaskKey (key,4)

c#
int key[]=new ...