一般建议不要先声明API再去调用,直接调用更方便也更节省资源(除非有特殊的数据类型必须通过声明API来指定)。
示例:
::User32.MessageBox(0,"测试","标题",0)
添加参数的规则
调用约定在加载DLL的参数中指定,支持cdecl不定个数参数,有很多API根据不同的用法可以传入不同类型的参数, 如果我们在aardio中不是先写一个API声明,而是直接去调用API,这时候就可以根据需要更灵活的改变参数类型。一般建议不要先声明API再去调用 - 直接调用更方便也更节省资源(除非有特殊的数据类型必须通过声明API来指定)。
null参数不可省略
数值参数一律处理为32位int整型,32位整数类型,小于32位的整数、枚举类型、8位或32位bool值都跟int 32位数值兼容,可以直接写在参数里,示例:
32位整型以及小于32位的整型参数都可以直接传入aardio数值。
例如C语言API声明为:void setNumber( short n )
在aardio里如下调用就可以dll.setNumber( 123 )
64位整数(C语言中的long long)可以math.size64对象表示,或者用两个数值参数表示一个64位整数值参数,其中第一个参数表示低32位数值,第二个参数表示高32位数值(一般可以直接写0)。
对于任何数值类型的指针(输出参数)一律使用结构体表示,
例如C语言API声明为:void getNumber( short *n )
在aardio里如下调用就可以
1 | var n = { word value } |
API函数中的数组指针,在
aardio
中可以使用结构体指针替代,例如C语言中的int data[4];
在aardio中写为{int data[4];}
如果是字节数组指针也可以使用raw.buffer()
函数创建的字节数组替代。所有结构体一律处理为输出参数并在
aardio
返回值中返回,其他类型只能作为输入参数。注意在aardio
中,任何结构体在API调用中传递的都是结构体指针(传址)。因为没有参数类型声明,调用代码有责任事先检查并保证参数类型正确,传入错误的参数可能导致程序异常。
获取返回值的规则
直接调用API的 返回值默认为
int
类型可以使用
[API尾标]
改变返回值为其他类型未声明的 API函数自身在
aardio
中是一个普通的aardio
函数对象,不能作为函数指针参数传给 API参数(声明后的API函数对象是可以的)
使用 [ API 尾标 ]
当不声明直接调用API时,API函数名尾部如果不是大写字符,则可以使用一个大写的特定字符(API尾标)修改默认的API调用规则,在API函数名后添加尾标,不会影响到查找API函数的结果,无论真实的API带不带指定的尾标 - aardio都能找到真实的函数。 所有可用的[API尾标]如下(函数名的最后一个特定字符是尾标):
dll.ApiNameW()
切换到Unicode
版本,字符串UTF8
<->UTF16
双向转换dll.ApiNameA()
切换到ANSI
版本,字符串不作任何转换dll.ApiNameL()
返回值为64位LONG
类型dll.ApiNameP()
返回值为指针类型dll.ApiNameD()
返回值为double
浮点数dll.ApiNameF()
返回值为float
浮点数dll.ApiNameB()
返回值为 C++ 中的8位bool
类型->
如何使用字符串
字符串一般直接转换为字符串指针,
buffer
类型字节数组也可以作为字符串指针使用,如果API需要向字符串指向的内存中写入数据,那么必须使用raw.buffer()
函数创建定长的字节数组。普通的aardio
字符串指向的内存是禁止写入的(aardio
中修改普通字符串会返回新的字符串对象,而不是在原内存上修改数据)对于非
Unicode
API字符串直接输入原始的数据(对于文本就是UTF8编码),对于声明为Unicode
版本的API,字符串会被强制转换为Unicode(UTF16)
,但buffer
类型的参数仍然会以二进制方式使用原始数据与API交互(不会做文本编码转换)可以在
raw.loadDll()
加载 DLL时在调用约定中添加,unicode
声明一个 DLL默认使用Unicode API
。也可以在函数名后添加尾标
W
声明一个Unicode API
, 即使真实的API函数名后面并没有W
尾标,你仍然可以添加W
尾标调用 API。aardio
在找不到该 API函数时,会移除W
尾标,并且认为该 API函数是一个Unicode API
,注意W
必须大写并紧跟在小写字母后面。直接调用 API时,如果目标 API函数并不存在,而是存在加
W
尾标的Unicode API
,aardio
将会自动切换到Unicode API
,并在调用函数时,自动将aardio
的UTF8
编码转换为 API所需要的UTF16
编码。反之,在API函数名后也可以显式的添加
A
尾标强制声明此 API是一个ANSI
版本的函数(对字符串参数不使用任何Unicode
转换,即使加载 DLL时在调用约定中声明了默认以unicode
方式调用),规则同上 - 也即真实的API函数名后面有没有A
尾标并不重要,在aardio
中都可以加上A
尾标。
一些API在接收字符串、字节数组等参数时,通常下一个参数需要指定内存长度,
aardio
中用#
操作符取字符串、缓冲区的长度时,返回的都是字节长度,一些 API可能需要你传入字符个数, 发果是Unicode
版本的 API一个字符为两个字节,对于一个UTF8
字符串应当事用string.len()
函数得到真正的字符长度, 而Unicode
字符串则用#
取到字节长度后乘以2即可。