我想在运行时从.NET代码解析来自C stdlib的函数的地址,例如malloc
的函数(因此我可以JIT为我的VM调用这些地址的机器代码)。我相信我应该使用LoadLibrary
和GetProcAddress
提供kernel32.dll,但这不起作用。使用F#interactive我得到:
> [<DllImport("kernel32.dll", CharSet=CharSet.Ansi, SetLastError=true)>]
extern IntPtr LoadLibrary(string fileName);;
val LoadLibrary : string -> IntPtr
> [<DllImport("kernel32.dll", CharSet=CharSet.Ansi, SetLastError=true)>]
extern uint32 GetProcAddress(IntPtr hModule, string fn);;
val GetProcAddress : IntPtr * string -> uint32
> let kernel32 = LoadLibrary @"kernel32.dll";;
val kernel32 : IntPtr = 1993146368n
> let malloc = GetProcAddress(kernel32, "malloc");;
val malloc : uint32 = 0u
所以这似乎已经获得了DLL的句柄但是尝试解析malloc
已经返回了一个NULL指针。
我该怎么做?
答案 0 :(得分:3)
AFAIK malloc
不属于kernel32.dll
。它是MS C运行时DLL的一部分 - 因为您没有提供有关如何/在何处使用它的任何详细信息,只提供了一些链接和相关信息:
基本上你必须加载相应的DLL,然后解析所需的功能,例如:
let SomeMSCRT = LoadLibrary @"SomeMSCRT.dll";;
let malloc = GetProcAddress(SomeMSCRT, "malloc");;
但需注意一点:
根据您想要做什么,您可能会遇到严重且难以调试的问题 - 例如,使用来自F#的malloc
是恕我直言的一个坏主意...您需要记住C运行时需要正确的初始化(在MS CRT的情况下,你需要首先调用CRT_INIT
)等等.C运行时不知道任何.NET细节,因此可能导致不稳定的行为...尤其是。因为CLR可能在内部使用CRT(可能是不同的版本)......
另一点:
在运行时生成机器代码并通过跳转到该内存区域来执行它需要采取多种安全措施(取决于Windows版本等)。您可能需要将相应的内存段标记为“可执行”,这是通过C运行时无法实现的,只能使用具有适当权限的Windows API调用(如VirtualAllocEx
)...查看起点{{ 3}}和here。
答案 1 :(得分:3)
我不相信malloc
是kernel32.dll
的一部分。但是,如果我没记错的话,所有malloc
实施最终都会深入到HeapAlloc kernel32.dll
。
答案 2 :(得分:2)
我想解析 C stdlib
中的函数地址
有你的问题。你说话就好像有一个C运行时库。实际上有很多。每个编译器都提供它自己的几种不同的版本(调试,发布,静态链接,动态链接),并且所有这些都是互不兼容的。
如果你知道你试图使用哪一个,你问题的答案就会变得很明显。
如果您希望在所有Windows应用程序之间共享操作系统提供的库,那么kernel32.dll
是正确的查找位置,但这些函数符合Win32 API规范,而不是ANSI或ISO C标准。