[入门] 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写在哪里呢?不然叫调用者用编译器修饰过的函数名觉得很别扭
Global site tag (gtag.js) - Google Analytics