繁体   English   中英

如何将sqlite3 +扩展功能静态链接到C / C ++应用程序?

[英]How to statically link sqlite3 + extension functions into a C / C++ application?

我已经将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

也许我是盲人,但是函数原型在test.cc中给出,函数定义在extension_functions.c中给出。 有谁知道这个代码示例有什么问题吗? 预先感谢您的帮助。(对于hxxp://链接,我们深表歉意,但我不允许发布两个以上的链接)

不要将C语言“链接”的概念与将一组编译函数物理地“链接”到完整程序中的过程相混淆。 后者是与源代码编译在逻辑上分开的操作,尽管其中一个受到前者的影响。

预处理程序宏会影响代码的编译方式,但不会(直接)影响代码的链接方式。 您的扩展功能可能需要使用-DSQLITE_CORE进行编译(尽管我对此不太确定),但是您需要链接选项来构建整体可执行文件。 您还需要SQLite库的静态版本。

GCC提供了一个用于编译和链接的公共前端( gcc ),因此您需要做的主要事情是(在链接阶段)通过gcc一个选项,指导它执行静态链接。 该选项拼写为-static

在混合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 ++的外部对象生成不同的符号。 错误消息反映出:

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 ++编译器通常通过将函数参数的原型作为符号名称的一部分来为这些不同的函数分配不同的符号。 相反,像int foobar()这样的C函数带有任何函数参数,只会在符号名称中没有符号原型的情况下生成符号foobar ,因为简单地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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM