aardio 文档
aardio 范例: C 扩展插件
import tcc;
import sqlite;
import console;
// 1. 设置 C 编译器
var c = tcc();
c.addLib("user32", "kernel32", "gdi32");
// 2. 编写 C 源码 (Hello World 版)
c.code = /**
#include <windows.h>
typedef struct sqlite3 sqlite3;
typedef struct sqlite3_context sqlite3_context;
typedef struct sqlite3_value sqlite3_value;
typedef struct sqlite3_stmt sqlite3_stmt;
typedef struct sqlite3_module sqlite3_module;
typedef void * sqlite3_callback;
typedef __int64 sqlite_int64;
typedef unsigned __int64 sqlite_uint64;
//tcc 轻量编译,无需配置 C 环境
//干净利落直接定义 sqlite3_api_routines,避免依赖 sqlite 头文件
typedef struct sqlite3_api_routines {
void * (*aggregate_context)(sqlite3_context*,int nBytes);
int (*aggregate_count)(sqlite3_context*);
int (*bind_blob)(sqlite3_stmt*,int,const void*,int n,void(*)(void*));
int (*bind_double)(sqlite3_stmt*,int,double);
int (*bind_int)(sqlite3_stmt*,int,int);
int (*bind_int64)(sqlite3_stmt*,int,sqlite_int64);
int (*bind_null)(sqlite3_stmt*,int);
int (*bind_parameter_count)(sqlite3_stmt*);
int (*bind_parameter_index)(sqlite3_stmt*,const char*zName);
const char * (*bind_parameter_name)(sqlite3_stmt*,int);
int (*bind_text)(sqlite3_stmt*,int,const char*,int n,void(*)(void*));
int (*bind_text16)(sqlite3_stmt*,int,const void*,int,void(*)(void*));
int (*bind_value)(sqlite3_stmt*,int,const sqlite3_value*);
int (*busy_handler)(sqlite3*,int(*)(void*,int),void*);
int (*busy_timeout)(sqlite3*,int ms);
int (*changes)(sqlite3*);
int (*close)(sqlite3*);
int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*,
int eTextRep,const char*));
int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*,
int eTextRep,const void*));
const void * (*column_blob)(sqlite3_stmt*,int iCol);
int (*column_bytes)(sqlite3_stmt*,int iCol);
int (*column_bytes16)(sqlite3_stmt*,int iCol);
int (*column_count)(sqlite3_stmt*pStmt);
const char * (*column_database_name)(sqlite3_stmt*,int);
const void * (*column_database_name16)(sqlite3_stmt*,int);
const char * (*column_decltype)(sqlite3_stmt*,int i);
const void * (*column_decltype16)(sqlite3_stmt*,int);
double (*column_double)(sqlite3_stmt*,int iCol);
int (*column_int)(sqlite3_stmt*,int iCol);
sqlite_int64 (*column_int64)(sqlite3_stmt*,int iCol);
const char * (*column_name)(sqlite3_stmt*,int);
const void * (*column_name16)(sqlite3_stmt*,int);
const char * (*column_origin_name)(sqlite3_stmt*,int);
const void * (*column_origin_name16)(sqlite3_stmt*,int);
const char * (*column_table_name)(sqlite3_stmt*,int);
const void * (*column_table_name16)(sqlite3_stmt*,int);
const unsigned char * (*column_text)(sqlite3_stmt*,int iCol);
const void * (*column_text16)(sqlite3_stmt*,int iCol);
int (*column_type)(sqlite3_stmt*,int iCol);
sqlite3_value* (*column_value)(sqlite3_stmt*,int iCol);
void * (*commit_hook)(sqlite3*,int(*)(void*),void*);
int (*complete)(const char*sql);
int (*complete16)(const void*sql);
int (*create_collation)(sqlite3*,const char*,int,void*,
int(*)(void*,int,const void*,int,const void*));
int (*create_collation16)(sqlite3*,const void*,int,void*,
int(*)(void*,int,const void*,int,const void*));
int (*create_function)(sqlite3*,const char*,int,int,void*,
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*));
int (*create_function16)(sqlite3*,const void*,int,int,void*,
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*));
int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*);
int (*data_count)(sqlite3_stmt*pStmt);
sqlite3 * (*db_handle)(sqlite3_stmt*);
int (*declare_vtab)(sqlite3*,const char*);
int (*enable_shared_cache)(int);
int (*errcode)(sqlite3*db);
const char * (*errmsg)(sqlite3*);
const void * (*errmsg16)(sqlite3*);
int (*exec)(sqlite3*,const char*,sqlite3_callback,void*,char**);
int (*expired)(sqlite3_stmt*);
int (*finalize)(sqlite3_stmt*pStmt);
void (*free)(void*);
void (*free_table)(char**result);
int (*get_autocommit)(sqlite3*);
void * (*get_auxdata)(sqlite3_context*,int);
int (*get_table)(sqlite3*,const char*,char***,int*,int*,char**);
int (*global_recover)(void);
void (*interruptx)(sqlite3*);
sqlite_int64 (*last_insert_rowid)(sqlite3*);
const char * (*libversion)(void);
int (*libversion_number)(void);
void *(*malloc)(int);
char * (*mprintf)(const char*,...);
int (*open)(const char*,sqlite3**);
int (*open16)(const void*,sqlite3**);
int (*prepare)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
int (*prepare16)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
void * (*profile)(sqlite3*,void(*)(void*,const char*,sqlite_uint64),void*);
void (*progress_handler)(sqlite3*,int,int(*)(void*),void*);
void *(*realloc)(void*,int);
int (*reset)(sqlite3_stmt*pStmt);
void (*result_blob)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_double)(sqlite3_context*,double);
void (*result_error)(sqlite3_context*,const char*,int);
void (*result_error16)(sqlite3_context*,const void*,int);
void (*result_int)(sqlite3_context*,int);
void (*result_int64)(sqlite3_context*,sqlite_int64);
void (*result_null)(sqlite3_context*);
void (*result_text)(sqlite3_context*,const char*,int,void(*)(void*));
void (*result_text16)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_text16be)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_value)(sqlite3_context*,sqlite3_value*);
void * (*rollback_hook)(sqlite3*,void(*)(void*),void*);
int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,
const char*,const char*),void*);
void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*));
char * (*snprintf)(int,char*,const char*,...);
int (*step)(sqlite3_stmt*);
int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,
char const**,char const**,int*,int*,int*);
void (*thread_cleanup)(void);
int (*total_changes)(sqlite3*);
void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*);
int (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*);
void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*,
sqlite_int64),void*);
void * (*user_data)(sqlite3_context*);
const void * (*value_blob)(sqlite3_value*);
int (*value_bytes)(sqlite3_value*);
int (*value_bytes16)(sqlite3_value*);
double (*value_double)(sqlite3_value*);
int (*value_int)(sqlite3_value*);
sqlite_int64 (*value_int64)(sqlite3_value*);
int (*value_numeric_type)(sqlite3_value*);
const unsigned char * (*value_text)(sqlite3_value*);
const void * (*value_text16)(sqlite3_value*);
const void * (*value_text16be)(sqlite3_value*);
const void * (*value_text16le)(sqlite3_value*);
int (*value_type)(sqlite3_value*);
char *(*vmprintf)(const char*,va_list);
int (*overload_function)(sqlite3*, const char *zFuncName, int nArg);
/*
以下是 v3.3.13 以上版本添加的函数。
如果需要后面的函数,请在 sqlite3ext.h 中找到定义补充到这里。
void *p[10]; //例如省略 10 个函数定义可以这样写
*/
} sqlite3_api_routines;
static const sqlite3_api_routines *sqlite3_api = 0;
// 简化宏调用
#define sqlite3_create_function sqlite3_api->create_function
#define sqlite3_result_int sqlite3_api->result_int
#define sqlite3_result_text sqlite3_api->result_text
#define sqlite3_result_blob sqlite3_api->result_blob
#define sqlite3_result_double sqlite3_api->result_double
#define sqlite3_result_error sqlite3_api->result_error
#define sqlite3_result_error16 sqlite3_api->result_error16
#define sqlite3_result_int64 sqlite3_api->result_int64
#define sqlite3_result_null sqlite3_api->result_null
#define sqlite3_result_text16 sqlite3_api->result_text16
#define sqlite3_result_text16be sqlite3_api->result_text16be
#define sqlite3_result_text16le sqlite3_api->result_text16le
#define sqlite3_result_value sqlite3_api->result_value
#define sqlite3_value_int sqlite3_api->value_int
#define sqlite3_value_text sqlite3_api->value_text
#define sqlite3_value_blob sqlite3_api->value_blob
#define sqlite3_value_bytes sqlite3_api->value_bytes
#define sqlite3_value_bytes16 sqlite3_api->value_bytes16
#define sqlite3_value_double sqlite3_api->value_double
#define sqlite3_value_int64 sqlite3_api->value_int64
#define sqlite3_value_numeric_type sqlite3_api->value_numeric_type
#define sqlite3_value_text16 sqlite3_api->value_text16
#define sqlite3_value_text16be sqlite3_api->value_text16be
#define sqlite3_value_text16le sqlite3_api->value_text16le
#define sqlite3_value_type sqlite3_api->value_type
#define SQLITE_UTF8 1
#define SQLITE_DETERMINISTIC 0x800
#define SQLITE_OK 0
#define SQLITE_STATIC ((void(*)(void*))0)
#define SQLITE_TRANSIENT ((void(*)(void*))-1)
static void func_hello(sqlite3_context *ctx, int argc, sqlite3_value **argv) {
const char *name = (const char *)sqlite3_value_text(argv[0]);
char buffer[256];
// 简单的字符串格式化 (注意: 生产环境应使用 sqlite3_mprintf 防止溢出)
if(name){
wsprintf(buffer, "Hello, %s!", name);
} else {
wsprintf(buffer, "Hello, World!");
}
// 返回文本结果 (-1 表示自动计算长度, SQLITE_TRANSIENT 表示需要拷贝字符串)
sqlite3_result_text(ctx, buffer, -1, SQLITE_TRANSIENT);
}
static void func_add(sqlite3_context *ctx, int argc, sqlite3_value **argv) {
int a = sqlite3_value_int(argv[0]);
int b = sqlite3_value_int(argv[1]);
sqlite3_result_int(ctx, a + b);
}
__declspec(dllexport) int sqlite3_extension_init(sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi) {
sqlite3_api = pApi;
sqlite3_create_function(db, "hello", 1, SQLITE_UTF8, 0, func_hello, 0, 0);
sqlite3_create_function(db, "my_add", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, func_add, 0, 0);
return SQLITE_OK;
}
**/
// 3. 编译生成 DLL
var dllPath = "/simple_ext.dll"
c.output( dllPath )
c.close();
// 4. 在打开数据库前注册 SQLite 插件
var ok,err = sqlite.autoExtension("sqlite3_extension_init",
"/simple_ext.dll" //改为 $"/simple_ext.dll","simple_ext" 自内存加载 DLL
)
assert(ok,err);
// 5. 测试调用
var db = sqlite(":memory:");
/*
加载扩展插件到指定数据库,此函数自动调用 db.enableLoadExtension(true)
而在版本低于 SQLite v3.12.0 时 db.enableLoadExtension(true) 会同时启用 SQL 加载扩展的能力。
而 sqlite.autoExtension 在任何版本都仅对 C API 生效,更为安全。
并且 db.loadExtension 不支持内存 DLL。
*/
// db.loadExtension("/simple_ext.dll","sqlite3_extension_init");
var resultAdd = db.stepQuery("SELECT my_add(100, 50) AS value")
console.expect(resultAdd.value,150,"100 + 50:");
// 7. 测试字符串
var resultStr = db.stepQuery("SELECT hello('Developer') AS value")
console.expect(resultStr.value,'Hello, Developer!',"测试字符串:");
// 8. 统计测试结果
console.pause();
//控制台全部输出如下:
/*
100 + 50: ✓ PASS
测试字符串: ✓ PASS
════════════════════════════
All tests ✓ 成功
Passed: 2
Failed: 0
════════════════════════════
*/
Markdown 格式