【问题标题】:Which threading mode is Sqlite for iOS compiled in Swift?Swift 中编译的 Sqlite for iOS 是哪种线程模式?
【发布时间】:2017-03-18 08:11:11
【问题描述】:

页面http://www.sqlite.org/threadsafe.html 提到:

单线程

多线程

序列化

我们如何在 Swift 中实现这些线程。或者如何在 Swift 中使用sqlite3_config(SQLITE_CONFIG_MULTITHREAD

【问题讨论】:

标签: ios swift sqlite


【解决方案1】:

您可以在打开数据库时添加所需的选项,而不是 sqlite3_config。这仅适用于sqlite3_open_v2,不适用于sqlite3_opensqlite3_open16

这是一个例子:

let rc = sqlite3_open_v2(databasePath, &db, SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE|SQLITE_OPEN_FULLMUTEX, nil)

【讨论】:

  • 如果我用sqlite3_open_v2(databasePath, &db,SQLITE_OPEN_FULLMUTEX, nil)打开数据库,我可以在一个进程中打开并在另一个进程打开和读取的同时写入?
【解决方案2】:

对于最终来到这里寻找使用内置 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)

【讨论】:

    猜你喜欢
    • 2012-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-15
    相关资源
    最近更新 更多