Я не могу передать функцию обратного вызова с новым аргументом, который я добавил в c - PullRequest
1 голос
/ 01 марта 2020

Я не знаю, как передать переменную в обратный вызов, чтобы сделать некоторые вещи (вывод json) внутри этой функции.

В примере кода нет других функций, которые мне нужно передать, но с sqlite3 Я думаю, что я должен сделать это в обратном вызове, скажите мне, если я делаю неправильно.

Обратный вызов вызывается в функции sendhosts () в моем коде.

Я получаю это ошибка:

В функции 'sendhosts': пример. c: 85: 48: ошибка: слишком мало аргументов для функции 'обратного вызова' r c = sqlite3_exe c (db, "SELECT * FROM hosts; ", callback (req), 0, & zErrMsg);

Исходный код :

#include <stdio.h>
#include <sqlite3.h>

static int callback(void *NotUsed, int argc, char **argv, char **azColName){
  int i;
  for(i=0; i<argc; i++){
    printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
  }
  printf("\n");
  return 0;
}  
int main(int argc, char **argv){
  sqlite3 *db;
  char *zErrMsg = 0;
  int rc;

  if( argc!=3 ){
    fprintf(stderr, "Usage: %s DATABASE SQL-STATEMENT\n", argv[0]);
    return(1);
  }
  rc = sqlite3_open(argv[1], &db);
  if( rc ){
    fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
    sqlite3_close(db);
    return(1);
  }
  rc = sqlite3_exec(db, argv[2], callback, 0, &zErrMsg);
  if( rc!=SQLITE_OK ){
    fprintf(stderr, "SQL error: %s\n", zErrMsg);
    sqlite3_free(zErrMsg);
  }
  sqlite3_close(db);
  return 0;
}

Мой код :

#include <sys/types.h> /* size_t, ssize_t */
#include <stdarg.h> /* va_list */
#include <stddef.h> /* NULL */
#include <stdint.h> /* int64_t */
#include <stdlib.h>
#include <string.h> /* memset */
#include <stdio.h>

#include <kcgi.h>
#include <kcgihtml.h>
#include <sqlite3.h>
enum    page {
    PAGE_HOSTS,
    PAGE__MAX
};
enum    key {
    KEY_INTEGER, 
    KEY_FILE,
    KEY_PAGECOUNT,
    KEY_PAGESIZE,
    KEY__MAX
};
struct  tstrct {
    struct khtmlreq  req;
    struct kreq *r;
};
typedef void (*disp)(struct kreq *);
static void sendhosts(struct kreq *);

static const disp disps[PAGE__MAX] = {
    sendhosts, /* PAGE_SENDDATA */
};
static const struct kvalid keys[KEY__MAX] = {
    { kvalid_int, "integer" }, /* KEY_INTEGER */
    { NULL, "file" }, /* KEY_FILE */
    { kvalid_uint, "count" }, /* KEY_PAGECOUNT */
    { kvalid_uint, "size" }, /* KEY_PAGESIZE */
};
static const char *const pages[PAGE__MAX] = {
    "sendhosts" /* PAGE_SENDDATA */
};
static void
resp_open(struct kreq *req, enum khttp http)
{
    enum kmime   mime;
    if (KMIME__MAX == (mime = req->mime))
        mime = KMIME_APP_OCTET_STREAM;

    khttp_head(req, kresps[KRESP_STATUS], 
        "%s", khttps[http]);
    khttp_head(req, kresps[KRESP_CONTENT_TYPE], 
        "%s", kmimetypes[mime]);
    khttp_body(req);
}
static int callback(struct kreq *req, int argc, char **argv, char **azColName){
    char        *page;
    struct khtmlreq  r;
    resp_open(req, KHTTP_200);
    khtml_open(&r, req, 0);
  int i;
  for(i=0; i<argc; i++){
    printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
    struct khtmlreq r;
    khtml_puts(&r, "OK");
  }
    khtml_close(&r);
    free(page);
}
static void
sendhosts(struct kreq *req)
{
    sqlite3 *db;
    char *zErrMsg = 0;
    int rc;
    rc = sqlite3_open("/var/www/MaSSH/databases/massh.db", &db);
    if(rc){
        sqlite3_close(db);
    }
    rc = sqlite3_exec(db, "SELECT * FROM hosts;", callback(req), 0, &zErrMsg);
    if(rc!= SQLITE_OK){
        sqlite3_free(zErrMsg);
    }
    sqlite3_close(db);
}
int
main(void)
{
    struct kreq  r;
    enum kcgi_err    er;

    /* Set up our main HTTP context. */

    er = khttp_parse(&r, keys, KEY__MAX, 
        pages, PAGE__MAX, PAGE_HOSTS);

    if (KCGI_OK != er)
        return(EXIT_FAILURE);

    /* 
     * Accept only GET, POST, and OPTIONS.
     * Restrict to text/html and a valid page.
     * If all of our parameters are valid, use a dispatch array to
     * send us to the page handlers.
     */

    if (KMETHOD_OPTIONS == r.method) {
        khttp_head(&r, kresps[KRESP_ALLOW], 
            "OPTIONS GET POST");
        resp_open(&r, KHTTP_200);
    } else if (KMETHOD_GET != r.method && 
           KMETHOD_POST != r.method) {
        resp_open(&r, KHTTP_405);
    } else if (PAGE__MAX == r.page || 
           KMIME_TEXT_HTML != r.mime) {
        resp_open(&r, KHTTP_404);
    } else
        (*disps[r.page])(&r);

    khttp_free(&r);
    return(EXIT_SUCCESS);
}

1 Ответ

0 голосов
/ 01 марта 2020

Подпись вашего обратного вызова

static int callback(struct kreq *req, int argc, char **argv, char **azColName)

неверна. Это должно быть

static int callback(void *ptr, int argc, char **argv, char **azColName) {
    struct kreq *req = (struct kreq *)ptr;

Подпись обратного вызова должна точно соответствовать формату указателя функции, который для sqlite3_exec, равен int (*callback)(void *, int, char **, char **).

И это

rc = sqlite3_exec(db, "SELECT * FROM hosts;", callback(req), 0, &zErrMsg);

должен быть

rc = sqlite3_exec(db, "SELECT * FROM hosts;", callback, req, &zErrMsg);

callback(req), звонит callback, что не то, что вы хотите; вы пытаетесь передать указатель на функцию, что делается только с помощью имени функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...