对于最终来到这里寻找使用内置 SQLite3 模块调用 sqlite3_config(不管线程问题)的方法的任何人...
它不可用的原因是它使用省略号样式的可变参数,根据this,Swift 不支持这些参数。解决此问题的一种方法是使用包装函数制作您自己的 C 标头,以便使用您需要的任何(非可变参数)参数排列调用 sqlite3_config。
例如,类似这样的“桥接头”涵盖了您可能需要的所有有效调用签名(就 SQLite 配置选项的要求而言):
#ifndef SqliteConfig_h
#define SqliteConfig_h
#import "sqlite3.h"
static inline int sqlite3_config_no_args(int op) {
return sqlite3_config(op);
}
static inline int sqlite3_config_ptr(int op, void* arg1) {
return sqlite3_config(op, arg1);
}
static inline int sqlite3_config_int(int op, int arg1) {
return sqlite3_config(op, arg1);
}
static inline int sqlite3_config_ptr_int_int(int op, void* arg1, int arg2, int arg3) {
return sqlite3_config(op, arg1, arg2, arg3);
}
static inline int sqlite3_config_int_int(int op, int arg1, int arg2) {
return sqlite3_config(op, arg1, arg2);
}
static inline int sqlite3_config_ptr_ptr(int op, void* arg1, void* arg2) {
return sqlite3_config(op, arg1, arg2);
}
#endif /* SqliteConfig_h */
也许有更简洁或更惯用的方法来创建这些类型的包装器(而不是桥接头中的静态内联函数)。我不是这方面的专家。但考虑到它们只是包装调用,这似乎是一个很好的轻量级解决方法。
如果您不知道如何创建桥接头,可以四处搜索有关桥接头的更多信息。但简而言之:您可以通过转到 Build Settings/Swift Compiler - General/Objective-C Bridging Header 并将值设置为您创建的头文件名来“手动”创建桥接头(在创建 .h 文件之后)。如果您不这样做,您的 .h 文件将被忽略。或者,您可以通过将虚拟 .c 文件拖到项目中,删除该文件,然后编辑它创建的标头来自动创建一个(无需进入编译器设置)。或者,如果您更喜欢那里的代码而不是内联代码,则使用“真正的”C 文件来执行此操作。
有了这些,下面是一个使用 sqlite3_config 安装您自己的日志回调的示例:
import SQLite3
func errorLogCallback(_: OpaquePointer?, iErrCode: Int, zMsg: UnsafePointer<CChar>)
{
let s = String(cString: zMsg)
print("LOG:", iErrCode, s)
}
let cCallbackPtr: @convention(c) (OpaquePointer?, Int, UnsafePointer<CChar>) -> () = errorLogCallback
let rawPtr = unsafeBitCast(cCallbackPtr, to: UnsafeMutableRawPointer.self)
sqlite3_config_ptr_ptr(SQLITE_CONFIG_LOG, rawPtr, nil)