c++ - 如何将 sqlite3 + 扩展函数静态链接到 C/C++ 应用程序中?

标签 c++ c sqlite

我已经将 sqlite3.c 构建到我的应用程序中,并将 extension-functions.c (hxxps://www.sqlite.org/contrib) 构建到一个共享库中并且它工作正常,但是对于我正在处理的项目我必须将 sqlite3 + 扩展函数静态链接到 C++ 应用程序中。 我已经阅读了很多关于这个主题的资料,但我无法让它发挥作用。

最小示例(test.cc):

#include "sqlite3.h"
#include<cstdlib>

void sqlite3_extension_functions_init(void);
// typedef struct sqlite3_api_routines sqlite3_api_routines;
// int sqlite3_extension_functions_init(sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi);

int main(int argc,char *argv[]) {
    //  sqlite3_auto_extension( (void(*)(void))sqlite3_extension_functions_init );
    sqlite3_auto_extension( sqlite3_extension_functions_init );

    sqlite3 *database_;
    sqlite3_open_v2("test.db", &database_, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);

    sqlite3_close_v2(database_);

    return 0;
}

构建命令:

gcc -o test sqlite3.c extension_functions.c test.cc -lpthread -lm -ldl -DSQLITE_CORE

(-DSQLITE_CORE 没有影响?)

错误:

/tmp/ccPfaDLE.o: In function `main':
test.cc:(.text+0x10): undefined reference to `sqlite3_extension_functions_init()'
collect2: ld returned 1 exit status

改为使用注释行:

/tmp/ccrs9B0K.o: In function `main':
test.cc:(.text+0x10): undefined reference to `sqlite3_extension_functions_init(sqlite3*, char**, sqlite3_api_routines const*)'
collect2: ld returned 1 exit status

我使用的其他来源:

  • hxxp://books.google.de/books?vid=ISBN1449399649&q=209
  • hxxps://www.sqlite.org/loadext.html
  • hxxp://stackoverflow.com/a/1295765

可能是我瞎了,函数原型(prototype)在test.cc中给出,函数定义在extension_functions.c中。有人知道这个代码示例有什么问题吗?预先感谢您的帮助。(我很抱歉 hxxp://链接,但我不允许发布两个以上的链接)

最佳答案

混合使用 C 和 C++ 代码时,请确保在 C++ 端将 C 函数的声明标记为 C,如:

extern "C" {
    int sqlite3_extension_functions_init(sqlite3 *db, char **pzErrMsg, 
                                         const sqlite3_api_routines *pApi);
    // more declarations
}

编译器为声明为 C 或 C++ 的外部变量生成不同的符号。错误消息反射(reflect):

test.cc:(.text+0x10): undefined reference to `sqlite3_extension_functions_init(sqlite3*, char**, sqlite3_api_routines const*)'

在这种情况下,编译器准备了一个符号名称,因为它认为它正在处理 C++ 函数,而实际上驻留在 extension_functions.c 中的函数将是一个 C 函数,链接器应该期望解析不同的符号名称。此错误消息指出链接器无法解析基于 C++ 命名法的符号名称。

顺便说一下背景。是C++支持函数重载,而C不支持。所以在 C++ 中你可以有两个不同的函数:

extern void foobar(int x, int y);
extern void foobar(char const *x);

为了区分,C++编译器为这些不同的函数分配了不同的符号,通常是将函数参数的原型(prototype)作为符号名的一部分。相比之下,像 int foobar() 这样带有任何函数参数的 C 函数只会生成符号 foobar 而符号名称中没有参数原型(prototype),因为简单的 C 不会有函数重载。

这就是为什么声明 C 函数但必须可用于 C 和 C++ 的头文件通常结构如下:

#ifdef __cplusplus
extern "C" {
#endif
    /* Now follow declarations of C functions, such as extern int printf()
     * or whatever 
     */
#ifdef __cplusplus
}
#endif

关于c++ - 如何将 sqlite3 + 扩展函数静态链接到 C/C++ 应用程序中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28856061/

相关文章:

c - 为什么Eclipse CDT说: 'syntax error' ,但是编译没问题

django - 导入错误 : No module named '_sqlite3' in python3. 3

c++ - 堆 block 修改超过请求的大小

c++ - 如何提前终止另一个文件中定义的函数?

c++ - 带有 std::map<T*, U> 的程序是否具有明确定义的行为?

iPhone - 为什么编译器在为 ARM 架构构建时找不到某些包含?

c++ - 像计算机一样思考的策略

c - 这段代码我哪里出错了

java - Android - SQLiteDatabase 没有这样的表错误(代码 1)

android - 标记消失