从.NET动态解析C stdlib函数

时间:2012-03-29 17:53:22

标签: c# .net f# pinvoke getprocaddress

我想在运行时从.NET代码解析来自C stdlib的函数的地址,例如malloc的函数(因此我可以JIT为我的VM调用这些地址的机器代码)。我相信我应该使用LoadLibraryGetProcAddress提供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指针。

我该怎么做?

3 个答案:

答案 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)

我不相信mallockernel32.dll的一部分。但是,如果我没记错的话,所有malloc实施最终都会深入到HeapAlloc kernel32.dll

答案 2 :(得分:2)

  

我想解析 C stdlib

中的函数地址

有你的问题。你说话就好像有一个C运行时库。实际上有很多。每个编译器都提供它自己的几种不同的版本(调试,发布,静态链接,动态链接),并且所有这些都是互不兼容的。

如果你知道你试图使用哪一个,你问题的答案就会变得很明显。

如果您希望在所有Windows应用程序之间共享操作系统提供的库,那么kernel32.dll是正确的查找位置,但这些函数符合Win32 API规范,而不是ANSI或ISO C标准。