揰掵佲 发表于 2021-2-22 23:29:08

[转]动态调用函数DispCallFunc的使用

动态调用函数DispCallFunc的使用|http://bbs.eyuyan.com/read.php?tid=419746



这个WIN32API函数的功能很强大,网上资料也不多,微软官方连个详细的例程都没有,只有一个源码里有使用到,所以会用的人很少。今天就教大家使用这个API。它不仅可以调用系统提供的IUnknown接口类,还可以动态调用WIN32API的函数和DLL命令。
你没有看错,例程里有演示,调用UNICODE的W版的WIN32API:wsprintfW和MessageBoxW,分别为_cdecl和_stdcall的。
独特的思路,非正常的调用,就不详讲了。原理看例程就明白了。看个人悟性。


下来讲解这个DispCallFunc的正常使用。它就是专为调用接口而设计的,Disp就是IDispatch的意思,专门调用这种接口的。现在以IImgCtx为例,详细讲解它的使用。先看此API的声明。


第一个参数:实例指针
其实就是接口指IUnknown*,但是易语言在调用DLL命令时,如果声明为对象型的参数,就会传入IUnknown**接口指针的指针,就算勾选传址,也仍是传IUnknown**,这就不太合理了,API不总是传IUnknown**。所以对象型要转化成IUnknown*,才可以代入参数一。


第二个参数:函数虚表偏移量
就是你要调用的接口方法了,这些方法的函数地址,就是这样按地址顺序排列存贮在内存中,称为虚函数表。我们通过代入指定的偏移量,才可以调用指定的方法,这个参数很重要,写错值就调用失败,程序出错退出。首先,我们看一下接口声明文件,有接口的GUID和方法声明。


方法从0号开始排列,前三个是IUnknown的基本方法,每个接口都有一样的公共方法。从第3号开始才是自有的方法。这个偏移量的计算公式:
偏移量=序号×4
代入到参数二中。


第三个参数:调用约定
在VS的源码文件OAIDL.H里,我们看到这样的声明,这是枚举常量,看到CC_CDECL和CC_STDCALL就是我们常用的。

enum tagCALLCONV
    {    CC_FASTCALL    = 0,
    CC_CDECL    = 1,
    CC_MSCPASCAL    = CC_CDECL + 1,
    CC_PASCAL    = CC_MSCPASCAL,
    CC_MACPASCAL    = CC_PASCAL + 1,
    CC_STDCALL    = CC_MACPASCAL + 1,
    CC_FPFASTCALL    = CC_STDCALL + 1,
    CC_SYSCALL    = CC_FPFASTCALL + 1,
    CC_MPWCDECL    = CC_SYSCALL + 1,
    CC_MPWPASCAL    = CC_MPWCDECL + 1,
    CC_MAX    = CC_MPWPASCAL + 1
    }    CALLCONV;


第四个参数:返回值类型
如果有返回值,就必须填写类型,是VT_VARANT声明相同的。如果没有返回值,就填入0值,就会忽略第八个参数的返回值。


第五个参数:参数总数
这个值必须正确了,参数总数不正确,会调用失败的,严重会出错退出。没参数时必须代入0。


第六个参数:参数类型数组
这个参数非常重要,如果类型写不正确,转代和调用时就会失败,参数变体型里的类型反倒不重要。


第七个参数:参数数组
其实就是变体型指针数组,但是DLL命令不能直接代入变体型数组,易会自动将变体型数组的成员数据,头尾相接的复制到连续存贮的内存块里,不是每个成员有独立的指针,这又和易的IDE不够智能有,勾选传址也没用。必须像例程里取出变体型数组指针代入。


第八个参数:返回值
代不代入没作用,由第四个参数决定,声明了返回值类型,就必须代入。


其实接口的调用,就看过例程后,触类旁通了。
希望教程对你有帮助,只是分享一些编程的小技巧。



ghtuofzk 发表于 2022-12-11 11:25:53


支持开源~!感谢分享
页: [1]
查看完整版本: [转]动态调用函数DispCallFunc的使用