找回密码
 加入
搜索
查看: 21718|回复: 31

[原创] 如何用AU3调用自己用VC++写的dll函数

[复制链接]
发表于 2010-9-15 14:30:32 | 显示全部楼层 |阅读模式
本帖最后由 speedneeder 于 2010-9-17 13:30 编辑

这问题困扰我一个上午了,终于找到原因了,不敢藏私,和大家分享一下。

大家都知道,AU3下调用dll文件里的函数是很方便的,只要一个dllcall语句就可以了。
比如下面这个:
$result = DllCall("user32.dll", "int", "MessageBox", "hwnd", 0, "str", "若干文字", "str", "若干标题", "int", 0)
就是调用user32.dll文件之中的MessageBox函数,创建一个窗口。
但是如果要调用自己用vc++(我用的是vs2010)编写的dll文件之中的函数,似乎这样简单地使用就不会起作用,比如下面这个名叫dll.cpp的源码文件(用vs2010的dll模板建立,编译之后生成名为dll.dll的动态链接库),为了清晰起见,我将无关紧要的代码和注释去掉了,主要就一个很简单的求和函数:
...

int dlladd(int a, int b)
{        
        return a+b;
}
对应的dll.h文件中该函数的声明为:
_declspec(dllexport) int dlladd(int a, int b);
这样生成的dll.dll在引用和链接之后可以被vc++程序以dlladd的函数名正常调用,但是在au3之中,这样调用(调用之前别忘记把dll.dll文件拷贝到au3程序所在的目录):
$result = DllCall("dll.dll", "int", "dlladd","int", 12, "int", 12)
却无法正常使用。

原因有两个:

一是,c++支持重载,所以如果不做说明,编译生成的dll文件之中函数名字是会改变的,VC++程序会自动找到改名之后的函数,但是au3却无法找到,使用autoit3中文工具箱里自带的dll查看工具depends,查看dll.dll之中的导出函数,







可见dlladd被改名为类似“?dlladd@@YAHHHHH@z”这样的奇怪名字



这时候可以用这样的方式在au3之中调用:
$result = DllCall("dll.dll", "int", "?dlladd@@YAHHHHH@z","int", 12, "int", 12)
但这样未免太傻了,所以更好的办法是在dll.h文件之中加上extern关键字,表示这个将会被外部程序调用,于是vc++就不会自动将函数改名了:
extern "C" _declspec(dllexport) int dlladd(int a, int b);
当然也可以改dll.def文件

但是这样改了之后,还会出现错误,这就是第二个原因了,因为vc++的函数默认的调用方式为_cdecl,而au3默认的函数调用方式为_stdcall,所以还要在dllcall语句的函数返回值后面标注一下调用方式:
$result = DllCall("dll.dll", "int:cdecl", "dlladd","int", 12, "int", 12)
这样就可以正常调用自己编写的dll文件之中的函数了。
此外还要注意一下,返回值的问题,返回的$result其实是个数组,$result[0]之中才是存储函数的返回值的

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×

评分

参与人数 1金钱 +5 收起 理由
顽固不化 + 5 支持探索者

查看全部评分

发表于 2010-9-15 15:44:53 | 显示全部楼层
支持楼主的探索精神
发表于 2010-9-15 16:05:23 | 显示全部楼层
悄悄支持一下
发表于 2010-9-16 10:28:59 | 显示全部楼层
小细节大问题
发表于 2010-9-16 17:24:50 | 显示全部楼层
很强!感谢分享~~论坛因为有您更精彩~~~
发表于 2011-4-11 14:14:43 | 显示全部楼层
回复 1# speedneeder

支持
学习^_^
发表于 2011-4-11 15:32:50 | 显示全部楼层
新手学习学习了
发表于 2011-4-27 14:38:10 | 显示全部楼层
感谢你啊,我正是也遇到了这个问题,困扰了我一上午了,多谢多谢啊
发表于 2011-10-14 01:45:14 | 显示全部楼层
有待模仿。。。。。。。。。。。。
发表于 2011-10-14 05:29:45 | 显示全部楼层
所有准备给其他程序调用的dll函数,建议在声明时加上如下形式:
__declspec(dllexport) int __stdcall dlladd(int a, int b)
发表于 2011-10-15 16:43:07 | 显示全部楼层
Good!
Very Thanks!
发表于 2011-10-15 18:26:20 | 显示全部楼层
很好!
发表于 2011-10-16 10:47:41 | 显示全部楼层
学习了,很细节的技巧!
发表于 2011-12-17 16:27:23 | 显示全部楼层
怎么读取返回值的【0】下标?
发表于 2011-12-17 16:47:43 | 显示全部楼层
新手来学习的
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-3-29 05:01 , Processed in 0.085783 second(s), 22 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表