Win32下注册COM组件后对注册表产生的变动- -| 回首页 | 2005年索引 | - -避免pod2html时中文链接遭到损坏的方法

使用Win32::API模块导入DLL中函数的注意事项- -

                                      

使用Win32::API时需要注意的基本上就3点:
1、DLL中函数的calling convention必须为__stdcall型。这个应该是Win32::API的底层库中引入的一个假设,和Perl没关系;如果你用XS自己写DLL的调用过程,自然可以根据DLL中特定的calling convention自行调整调用方法,这一限制也就不复存在了。
2、导入DLL中的函数时要保证函数标识符的正确性。之所以要提这一点是因为在不使用definition file的情况下,不同的编译器在产生DLL时对导出函数名的处理方法不一样。以VC6为例,当调用规范为__cdecl时,函数func将被改名为_func;调用规范为__stdcall时,函数func被改名为_func@n,其中n是函数参数的总字节数。因此在导入函数之前最好用dumpbin之类的工具看一下DLL导出函数的真正标识符,必须用这种name mangling之后的标识符才能正常导入函数。为了避免这种麻烦,在写DLL的时候尽量用definition file指定每个函数生成的标识符吧。
3、用给出函数原型的方法导入函数时表示指针的*号一定要和类型紧挨着,另外这时对于指针类型的参数不需要自己pack数据了。例如:
假设test.dll中有一个函数long func(long *a),则
use Win32::API;
$handle=Win32::API->new('test','long func(long* a)'); # 这里指针符号*和指向的类型必须紧挨着,
# 这是由Win32::API解析原型的方法决定的。
$a=10; # 注意:不需要pack了!Win32::API会自动根据函数原型pack数据
$handle->Call($a);
不使用原型时,由于指针指向的对象类型未知,Win32::API无法知道如何处理这种数据,就必须手工将数据pack到标量中去。
$handle=Win32::API->new('test','func','P','N');
$a=pack('L',10);
$handle->Call($a);


Reference:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/_core_Calling_DLL_Functions_from_Visual_Basic_Applications.asp


- 作者: chaoslawful 访问统计: 2005年03月12日, 星期六 01:58 加入博采

Trackback

你可以使用这个链接引用该篇文章 http://publishblog.blogchina.com/blog/tb.b?diaryID=918884

回复

- 评论人:maning   2005-08-25 12:12:21 

您好,我有一个Perl中使用Win32::API的问题需要请教您.我们使用ActivePerl,调用_cdecl的DLL函数会有一个异常出现,而使用__stdcall则会出现一个"Array found"的错误.因为是第一次接触Perl,所以不知道该如何解决.如果能够得到您的指点,我将十分感谢.
我的邮件maning at vimicro.com,谢谢

- 评论人:Zuxy   2005-04-15 21:11:37 

呵呵,Pack原来就是box……这个词用得真不怎么样。

评论内容: