koffi中文
  • KOFFI
  • koffi性能
  • 中文更新日志
  • 安装需求
  • 开始使用
  • 函数调用
  • 输入参数
  • 数据指针
  • 输出参数
  • 多态参数
  • Union数据
  • 导出的变量
  • JAVASCRIPT 回调
  • 杂项
  • 构建工具和koffi
  • 贡献
  • 变更日志
  • 迁移指南
Powered by GitBook
On this page
  • 1.x to 2.x
  • 回调类型改变
  • 不透明类型更改
  • 新 koffi.introspect()

迁移指南

1.x to 2.x

API 在 2.x 中进行了一些更改,以减少一些过于“神奇”的行为并减少 C 和类 C 原型之间的语法差异。

如果您使用以下内容,您可能需要更改代码:

  • 回调函数

  • 不透明类型

  • koffi.introspect()

回调类型改变

在 Koffi 1.x 中,回调的定义方式使它们可以直接用作参数和返回类型,从而掩盖了底层指针。现在,您必须通过指针使用它们:在 Koffi 1.x 中void CallIt(CallbackType func)变为2.0 及更高版本void CallIt(CallbackType *func)。

#include <string.h>

int TransferToJS(const char *name, int age, int (*cb)(const char *str, int age))
{
    char buf[64];
    snprintf(buf, sizeof(buf), "Hello %s!", str);
    return cb(buf, age);
}
// Koffi 1.x

const TransferCallback = koffi.proto('int TransferCallback(const char *str, int age)');

const TransferToJS = lib.func('TransferToJS', 'int', ['str', 'int', TransferCallback]);
// Equivalent to: const TransferToJS = lib.func('int TransferToJS(str s, int x, TransferCallback cb)');

let ret = TransferToJS('Niels', 27, (str, age) => {
    console.log(str);
    console.log('Your age is:', age);
    return 42;
});
console.log(ret);
// Koffi 2.x

const TransferCallback = koffi.proto('int TransferCallback(const char *str, int age)');

const TransferToJS = lib.func('TransferToJS', 'int', ['str', 'int', koffi.pointer(TransferCallback)]);
// Equivalent to: const TransferToJS = lib.func('int TransferToJS(str s, int x, TransferCallback *cb)');

let ret = TransferToJS('Niels', 27, (str, age) => {
    console.log(str);
    console.log('Your age is:', age);
    return 42;
});
console.log(ret);

该函数koffi.proto()在Koffi 2.4中引入,koffi.callback()在早期版本中被调用。

不透明类型更改

在 Koffi 1.x 中,不透明句柄的定义方式使它们可以直接用作参数和返回类型,从而掩盖了底层指针。现在,在 Koffi 2.0 中,您必须通过指针使用它们,并使用数组作为输出参数。

除此之外,koffi.handle()在 Koffi 2.1 中已弃用并替换为koffi.opaque(). 它们的工作原理相同,但新代码应该使用koffi.opaque(),前一个最终将在 Koffi 3.0 中删除。

对于返回不透明指针或通过参数传递它们的函数:

// Koffi 1.x

const FILE = koffi.handle('FILE');
const fopen = lib.func('fopen', 'FILE', ['str', 'str']);
const fopen = lib.func('fclose', 'int', ['FILE']);

let fp = fopen('EMPTY', 'wb');
if (!fp)
    throw new Error('Failed to open file');
fclose(fp);
// Koffi 2.1

// If you use Koffi 2.0: const FILE = koffi.handle('FILE');
const FILE = koffi.opaque('FILE');
const fopen = lib.func('fopen', 'FILE *', ['str', 'str']);
const fopen = lib.func('fclose', 'int', ['FILE *']);

let fp = fopen('EMPTY', 'wb');
if (!fp)
    throw new Error('Failed to open file');
fclose(fp);

对于通过输出参数设置不透明句柄的函数(例如sqlite3_open_v2),您现在必须使用单个元素数组,如下所示:

// Koffi 1.x

const sqlite3 = koffi.handle('sqlite3');

const sqlite3_open_v2 = lib.func('int sqlite3_open_v2(const char *, _Out_ sqlite3 *db, int, const char *)');
const sqlite3_close_v2 = lib.func('int sqlite3_close_v2(sqlite3 db)');

const SQLITE_OPEN_READWRITE = 0x2;
const SQLITE_OPEN_CREATE = 0x4;

let db = {};

if (sqlite3_open_v2(':memory:', db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, null) != 0)
    throw new Error('Failed to open database');

sqlite3_close_v2(db);
// Koffi 2.1

// If you use Koffi 2.0: const sqlite3 = koffi.handle('sqlite3');
const sqlite3 = koffi.opaque('sqlite3');

const sqlite3_open_v2 = lib.func('int sqlite3_open_v2(const char *, _Out_ sqlite3 **db, int, const char *)');
const sqlite3_close_v2 = lib.func('int sqlite3_close_v2(sqlite3 *db)');

const SQLITE_OPEN_READWRITE = 0x2;
const SQLITE_OPEN_CREATE = 0x4;

let db = null;

let ptr = [null];
if (sqlite3_open_v2(':memory:', ptr, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, null) != 0)
    throw new Error('Failed to open database');
db = ptr[0];

sqlite3_close_v2(db);

新 koffi.introspect()

在 Koffi 1.x 中,koffi.introspect()仅适用于结构类型,并返回传递给koffi.struct()初始化类型的对象。现在这个函数适用于所有类型。

您仍然可以获得结构成员列表:

const StructType = koffi.struct('StructType', { dummy: 'int' });

// Koffi 1.x
let members = koffi.introspect(StructType);

// Koffi 2.x
let members = koffi.introspect(StructType).members;
Previous变更日志

Last updated 1 year ago

Koffi 1.x 仅支持,您必须使用 Koffi 2.x 来注册回调。

瞬态回调