如何使用 QThreadStorage 调用自定义免费?

Posted

技术标签:

【中文标题】如何使用 QThreadStorage 调用自定义免费?【英文标题】:How do I call a custom free with QThreadStorage? 【发布时间】:2014-02-03 20:16:16 【问题描述】:

我存储在 QThreadStorage 中的每个线程都有一个 sqlite3* 实例。问题是当我退出时,QThreadStorage 会删除指针。如何让它改为调用 sqlite3_close?

【问题讨论】:

【参考方案1】:

您需要将sqlite3* 指针以及sqlite3_stmt* 包装在RAII 类中。就像你应该做的那样,如果你用 C++ 而不是 C 编程:)

这样的类肯定存在,参见this question,例如麻省理工学院许可的sqlite3pp 项目。

一个不包含所有 API 的非常简单的实现,可以使用转换运算符使实例可以轻松地与 sqlite 的 C 接口函数一起使用。

// https://github.com/KubaO/***n/tree/master/questions/sqlite-threadstore-21536836
#include <QtCore>
#include <sqlite3.h>

class SQLiteStmt 
   Q_DISABLE_COPY(SQLiteStmt)
   sqlite3_stmt* m_stmt;
   int m_rc;
   friend class SQLiteDB;
private:
   explicit SQLiteStmt(sqlite3_stmt* stmt, int rc) : m_stmt(stmt), m_rc(rc) 
public:
   SQLiteStmt(SQLiteStmt && o) : m_stmt(o.m_stmt), m_rc(o.m_rc) 
      o.m_stmt = nullptr;
   
   ~SQLiteStmt()  sqlite3_finalize(m_stmt); m_stmt = nullptr; 
   int status() const  return m_rc; 
   operator sqlite3_stmt*() const  return m_stmt; 
;

class SQLiteDB 
   Q_DISABLE_COPY(SQLiteDB)
   sqlite3* m_db = nullptr;
public:
   SQLiteDB() = default;
   int open(const QString & filename) 
      close();
      return sqlite3_open16(filename.utf16(), &m_db);
   
   int close() 
      sqlite3* const db = m_db;
      m_db = nullptr;
      if (db) return sqlite3_close(db);
      return SQLITE_OK;
   
   int exec(const QString & sql) 
      auto stmt = prepare(sql);
      int rc = stmt.status();
      if (rc == SQLITE_OK) do 
         rc = sqlite3_step(stmt);
       while (rc == SQLITE_ROW);
      return rc;
   
   SQLiteStmt prepare(const QString & sql) 
      sqlite3_stmt* stmt;
      auto rc = sqlite3_prepare16_v2(m_db, sql.utf16(), -1, &stmt, nullptr);
      return SQLiteStmtstmt, rc;
   
   ~SQLiteDB()  close(); 
   operator sqlite3*() const  return m_db; 
;

int main() 
   QThreadStorage<SQLiteDB> dbData;
   SQLiteDB & db(dbData.localData());
   if (db.open(":memory:") != SQLITE_OK)
      qDebug() << "open failed";
   if (db.exec("CREATE TABLE myTable(value NUMERIC)") != SQLITE_DONE)
      qDebug() << "create failed";
   if (db.exec("INSERT INTO myTable VALUES (10), (20), (30)") != SQLITE_DONE)
      qDebug() << "insert failed";
   auto stmt = db.prepare("SELECT * FROM myTable");
   if (stmt.status() == SQLITE_OK) while (true) 
      int rc = sqlite3_step(stmt);
      if (rc != SQLITE_ROW) break;
      qDebug() << sqlite3_column_int(stmt, 0);
   

【讨论】:

Qt有提供这样的类吗? @chacham15 我猜他的意思只是创建一些类来存储您的sqlite3* 指针并在析构函数中调用sqlite3_close,这样如果您将此类的实例存储在QThreadStorage 您想要的函数中将在QThreadStorage析构函数中调用。 @Predelnik 是的,这就是我的想法,但我认为可能有一个内置类可以做到这一点,而不必自己动手。

以上是关于如何使用 QThreadStorage 调用自定义免费?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用反射调用自定义运算符

织梦CMS如何在自定义表单页调用arclist标签啊,怎么在自定义表单页调用无效!

如何在 C# 中调用自定义 url 协议?

eyoucms 文章列表如何调用自定义字段

如何使用google apps脚本在自定义函数中编辑自定义函数的调用单元格?

如何在 JNI 中使用自定义类类型参数调用 Java 函数