3

我正在使用sqlite3_exec带有静态回调函数的 SQLite 函数来处理一些信息。我想将结果信息打印到一个名为sqlite3_exec. 我说的有点像这样

class MakingTheCall{

static int CallBack(void *NotUsed, int argc, char **argv, char **azColName)
{
    for(int x = 0; x < argc; x++)
        File << argv[x];
    File<<"\n";
} 

private:
   static ofstream File;
   void call(){
       sqlite3_exec(database, query, callback, 0, &zErrMsg);
   }
};

真正想要的是静态函数使用特定于实例的FILE. 因此,无论哪个实例MakingTheCall进行调用都会传递它唯一的非静态FILE对象。

但是因为CallBack是静态的并且必须(我认为)是一个回调,所以它无法访问this类的指针。所以我的想法是如果函数所在的friend函数那么它可以到达this指针。这是假设我正确理解这篇文章。

我觉得我的思路有问题。感觉对于this该函数将使用哪个功能可能仍然存在歧义。

作为本次讨论的第 2 部分,是否有任何地方可以使用静态朋友方法的示例?从我在第一条评论中阅读的内容来看,它们并不是互斥的修饰符,所以你什么时候会同时使用它们?

我是 SQLite 和 CallBacks 的新手,所以我可能会在这里遗漏一些可以让我的生活变得轻松的东西。像void*指针我该如何使用它?感觉就像是我想做的事情的关键。

提前谢谢。

4

3 回答 3

4

sqlite3_exec()调用中传递对象指针:

sqlite3_exec(database, query, callback, (void*) this, &zErrMsg);

NotUsed你会在回调的参数中取回它:

static int CallBack(void *NotUsed, int argc, char **argv, char **azColName)
{
    MakingTheCall* obj = (MakingTheCall*) NotUsed;

    // whatever....
}

严格来说,Callback()函数应该是extern "C"自由函数,而不是静态成员。

于 2012-08-30T16:19:59.043 回答
4

如果您使用C++11-support 进行编译,则可以使用匿名函数(lambda 表达式)。例子:

class MakingTheCall
{
private:
   ofstream File;
   void call(){
       sqlite3_exec(database, query,
           [&] (void *NotUsed, int argc, char **argv, char **azColName) -> int
           {
               for(int x = 0; x < argc; x++)
               File << argv[x];
               File<<"\n";
           },
           0, &zErrMsg);
   }
};

[&]意味着,所有可用的变量call都通过引用捕获,包括this-pointer。有关详细信息,请参见此处(维基百科)

于 2012-08-30T16:51:23.077 回答
2

通常,这是通过在注册回调时将指向对象的指针作为闭包参数的一部分传递来实现的。API的情况sqlite3_exec如下:

int sqlite3_exec(
  sqlite3*,                                  /* An open database */
  const char *sql,                           /* SQL to be evaluated */
  int (*callback)(void*,int,char**,char**),  /* Callback function */
  void *,                                    /* 1st argument to callback */
  char **errmsg                              /* Error msg written here */
);

所以我会将指向对象的指针作为参数 4 传递。你的回调函数仍然是静态的,但它应该做的第一件事是将第一个参数转换为指向你感兴趣的对象类的指针。你可以然后调用所需的函数,该函数将允许您写入File特定于您已传递的实例的函数。所以你的代码可能看起来像这样:

static int CallBack(void *closure, int argc, char **argv, char **azColName)
{
    MakingTheCall* obj = static_cast<MakingTheCall*>(closure);
    obj->WriteToTheFile(argc, argv);
    return 0; // Have to return something.
}

int WriteToTheFile(int argc, char **argv)
{
    for(int x = 0; x < argc; x++)
        File << argv[x];
    File<<"\n";
} 
于 2012-08-30T16:24:44.760 回答