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 格式