簡體   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