不透明指针:库不公开结构的内容,只为您提供指向它的指针(例如FILE *)。只有库提供的函数才能使用该指针执行某些操作,在 Koffi 中我们将其称为不透明类型。这样做通常是出于 ABI 稳定性的原因,并防止库用户直接干扰库内部。
指向原始类型的指针:这种情况比较罕见,通常用于输出或输入/输出参数。Win32 API 有很多这样的API。
数组:在 C 中,动态大小的数组通常传递给带有指针的函数,指针可以是 NULL 终止的(或任何其他标记值),也可以是带有附加长度参数的指针。
指针类型
结构体指针
下面的 Win32 示例使用GetCursorPos()(带有输出参数)来检索并显示当前光标位置。
// ES6 syntax: import koffi from 'koffi';constkoffi=require('koffi');constlib=koffi.load('user32.dll');// Type declarationsconstPOINT=koffi.struct('POINT',{x:'long',y:'long'});// Functions declarationsconstGetCursorPos=lib.func('int __stdcall GetCursorPos(_Out_ POINT *pos)');// Get and show cursor positionletpos={};if (!GetCursorPos(pos))thrownewError('Failed to get cursor position');console.log(pos);
不透明指针
Koffi 2.0 中的新功能
一些 C 库使用句柄,其行为就像指向不透明结构的指针。Win32 API 中的 HANDLE 类型就是一个例子。如果要重现此行为,可以将命名指针类型定义为不透明类型,如下所示:
const HANDLE = koffi.pointer('HANDLE', koffi.opaque());
// And now you get to use it this way:
const GetHandleInformation = lib.func('bool __stdcall GetHandleInformation(HANDLE h, _Out_ uint32_t *flags)');
const CloseHandle = lib.func('bool __stdcall CloseHandle(HANDLE h)');
let list1 = [1, 2];
let list2 = list1;
list2[1] = 42;
console.log(list1); // Prints [1, 42]
void AddInt(int *dest, int add)
{
*dest += add;
}
const AddInt = lib.func('void AddInt(_Inout_ int *dest, int add)');
let sum = [36];
AddInt(sum, 6);
console.log(sum[0]); // Prints 42
// ES6 syntax: import koffi from 'koffi';
const koffi = require('koffi');
const lib = koffi.load('./length.so');
const ComputeTotalLength = lib.func('int64_t ComputeTotalLength(const char **strings)');
let strings = ['Get', 'Total', 'Length', null];
let total = ComputeTotalLength(strings);
console.log(total); // Prints 14
const AnonHeapStr = koffi.disposable('str'); // Anonymous type (cannot be used in function prototypes)
const NamedHeapStr = koffi.disposable('HeapStr', 'str'); // Same thing, but named so usable in function prototypes
const ExplicitFree = koffi.disposable('HeapStr16', 'str16', koffi.free); // You can specify any other JS function