一般建议不要先声明API再去调用,直接调用更方便也更节省资源(除非有特殊的数据类型必须通过声明API来指定)。

示例:

::User32.MessageBox(0,"测试","标题",0)

添加参数的规则

  1. 调用约定在加载DLL的参数中指定,支持cdecl不定个数参数,有很多API根据不同的用法可以传入不同类型的参数, 如果我们在aardio中不是先写一个API声明,而是直接去调用API,这时候就可以根据需要更灵活的改变参数类型。一般建议不要先声明API再去调用 - 直接调用更方便也更节省资源(除非有特殊的数据类型必须通过声明API来指定)。

  2. null参数不可省略

  3. 数值参数一律处理为32位int整型,32位整数类型,小于32位的整数、枚举类型、8位或32位bool值都跟int 32位数值兼容,可以直接写在参数里,示例:

32位整型以及小于32位的整型参数都可以直接传入aardio数值。
例如C语言API声明为:void setNumber( short n )
在aardio里如下调用就可以 dll.setNumber( 123 )

  1. 64位整数(C语言中的long long)可以math.size64对象表示,或者用两个数值参数表示一个64位整数值参数,其中第一个参数表示低32位数值,第二个参数表示高32位数值(一般可以直接写0)。

  2. 对于任何数值类型的指针(输出参数)一律使用结构体表示,
    例如C语言API声明为:void getNumber( short *n ) 在aardio里如下调用就可以

1
2
var n = { word value }
dll.getNumber(n)
  1. API函数中的数组指针,在aardio中可以使用结构体指针替代,例如C语言中的 int data[4]; 在aardio中写为 {int data[4];} 如果是字节数组指针也可以使用raw.buffer()函数创建的字节数组替代。

  2. 所有结构体一律处理为输出参数并在aardio返回值中返回,其他类型只能作为输入参数。注意在aardio中,任何结构体在API调用中传递的都是结构体指针(传址)。

  3. 因为没有参数类型声明,调用代码有责任事先检查并保证参数类型正确,传入错误的参数可能导致程序异常。

获取返回值的规则

  1. 直接调用API的 返回值默认为int类型

  2. 可以使用[API尾标]改变返回值为其他类型

  3. 未声明的 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类型

如何使用字符串

  1. 字符串一般直接转换为字符串指针,buffer类型字节数组也可以作为字符串指针使用,如果API需要向字符串指向的内存中写入数据,那么必须使用raw.buffer()函数创建定长的字节数组。普通的aardio字符串指向的内存是禁止写入的(aardio中修改普通字符串会返回新的字符串对象,而不是在原内存上修改数据)

  2. 对于非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,并在调用函数时,自动将aardioUTF8编码转换为 API所需要的UTF16编码。

    • 反之,在API函数名后也可以显式的添加 A 尾标强制声明此 API是一个 ANSI 版本的函数(对字符串参数不使用任何 Unicode 转换,即使加载 DLL时在调用约定中声明了默认以 unicode 方式调用),规则同上 - 也即真实的API函数名后面有没有 A 尾标并不重要,在aardio中都可以加上 A 尾标。

  3. 一些API在接收字符串、字节数组等参数时,通常下一个参数需要指定内存长度, aardio中用#操作符取字符串、缓冲区的长度时,返回的都是字节长度,一些 API可能需要你传入字符个数, 发果是Unicode版本的 API一个字符为两个字节,对于一个UTF8字符串应当事用string.len()函数得到真正的字符长度, 而Unicode字符串则用#取到字节长度后乘以2即可。