[入门] alias int (*FARPROC)()与DLL函数动态加载
tuja
2007-05-13
今天在学习调用DLL中的函数,要用到FARPROC数据类型,于是马上查标准库:
std.c.windows.windows中有一行: alias int (*FARPROC)(); 下面是粗浅的理解,不知道对不对,请教大家: 1 int (*FARPROC)()是C风格的匿名函数声明 相当于D风格的 int fuction() FARPROC 2 alias int (*FARPROC)()也就是 alias int function() FARPROC 也就是声明FARPROC是匿名函数int function()类型 这样声明的目的是便于书写 3 FARPROC fp声明了函数指针fp 等价于 int function() fp 下面对官方教程的注释是否正确? //MyDLL_Initialize_fp是匿名函数的别名,这样声明是便于书写 alias void function(void*) MyDLL_Initialize_fp; FARPROC fp; //fp是fuction()形式函数的指针 //声明匿名函数void function(void*)的指针mydll_initialize MyDLL_Initialize_fp mydll_initialize; //得到dll句柄 h = LoadLibraryA("mydll.dll"); //得到MyDLL_Initialize函数的远程指针 fp = GetProcAddress(h, "D5mydll16MyDLL_InitializeFPvZv"); //把远程指针转换到MyDLL_Initialize_fp类型指针,以和实际函数格式相匹配 mydll_initialize = cast(MyDLL_Initialize_fp) fp; //标识符前置*取出指针内容也就是实际函数,再调用函数 (*mydll_initialize)(std.gc.getGCHandle()); 对于指针刚刚了解一点点,肯定理解得不是那么完整,请大家指点上面的理解有什么不对的地方 |
|
qiezi
2007-05-13
这是个C语言的语法,就是定义函数指针类型,相当于alias int function() FARPROC。
|
|
tuja
2007-05-13
本来不明白,看到C风格匿名函数声明语法才看明白了。
感觉alias int (*FARPROC)(); 这样的语法很怪。看上去好像是alias int another; |
|
tuja
2007-05-13
火星上关于win32 dll的教程:
http://www.digitalmars.com/d/dll.html 有一点不明白,在test.d里动态或静态调用mydll.dll里的函数 还要test.d里import mydll.d 难道没有dll源文件就不能调用d写的dll吗 |
|
qiezi
2007-05-13
import的作用就是引入名称,没有这个名称,你如何调用方法?
|
|
tuja
2007-05-14
知道了。就象调用windows api一样,要先引入名称。
引入的mydll.d只要包含名称就可以了,不必包含源代码。 不过D中动态加载dll时,函数名要从map文件中找: fp = GetProcAddress(h, "D5mydll16MyDLL_InitializeFPvZv"); 但我看c++的例子,只要直接写出函数名就可以了,难道还不如c++方便吗? |
|
qiezi
2007-05-14
tuja 写道 知道了。就象调用windows api一样,要先引入名称。
引入的mydll.d只要包含名称就可以了,不必包含源代码。 不过D中动态加载dll时,函数名要从map文件中找: fp = GetProcAddress(h, "D5mydll16MyDLL_InitializeFPvZv"); 奇怪的论断,是哪篇文档告诉你的,还是你自己测试的结果?删掉.map文件不能执行? GetProcAddress是windows api,D怎么会改变它? tuja 写道 难道还不如c++方便吗? 即便真有你所说的情况,D也没有保证一定要各方面都比C++方便吧? |
|
tuja
2007-05-14
来自火星上关于win32 dll的教程:
http://www.digitalmars.com/d/dll.html MyDLL_Initialize是mydll.d里的一个函数名,通过动态加载mydll.dll调用MyDLL_Initialize函数,官方示例中就是用函数的修饰名作为GetProcAddress的参数的: fp = GetProcAddress(h, "D5mydll16MyDLL_InitializeFPvZv"); 文档这么说: An easy way to get the decorated name to pass to GetProcAddress() is to copy and paste it from the generated mydll.map file under the Export heading. |
|
qiezi
2007-05-14
tuja 写道 来自火星上关于win32 dll的教程: http://www.digitalmars.com/d/dll.html MyDLL_Initialize是mydll.d里的一个函数名,通过动态加载mydll.dll调用MyDLL_Initialize函数,官方示例中就是这么用的: fp = GetProcAddress(h, "D5mydll16MyDLL_InitializeFPvZv"); 文档这么说: An easy way to get the decorated name to pass to GetProcAddress() is to copy and paste it from the generated mydll.map file under the Export heading. 他是说,你要想得到经过编译器打乱后的名字,比如上面的:D5mydll16MyDLL_InitializeFPvZv,最好是产生.map文件,然后从它里面"copy and paste"出来。 如果你知道名字,或者是编译DLL时使用了alias,自然是不需要这个文件了。但alias的前提也是你得知道它这个打乱后的名字,最快捷的办法是生成一个map文件,这个文件起的作用就这么点。奇怪我生成的map文件里没有这个名字呢。。 |
|
tuja
2007-05-14
编译时加上参数 -L/map 才能生成完整的map文件。
文档上是这样用的: 1 编译obj文件 dmd -c mydll -g 2 编译dll并生成map文件 dmd mydll.obj gcstub.obj mydll.def -g -L/map gcstub.obj不是必需的。 3 生成导入库 implib /noi /system mydll.lib mydll.dll 生成dll时的alias写在哪里呢?不然叫调用者用编译器修饰过的函数名觉得很别扭 |