当我在C程序中链接静态库时,为什么会得到“未定义符号”?]

问题描述 投票:0回答:3
我正在尝试创建一个静态库,以允许我在C程序中使用C ++ API。首先,我正在尝试调用一个名为APIName::Api_init()的API函数。到目前为止,我已经创建了一个具有以下内容的“包装器”库:

c_api.h:

#ifdef __cplusplus #define EXTERNC extern "C" #else #define EXTERNC #endif EXTERNC int apiname_api_init(char const * user_app_name); EXTERNC void apiname_api_shutdown(); #undef EXTERNC

c_api.cpp:

#include "c_api.h" #include "../include/apiname/api.h" // Link to header files from API provider int apiname_api_init(char const * user_app_name) { return to_return_code(APIName::Api_init(user_app_name)); } void apiname_api_shutdown() { return APIName::api_shutdown(); }

然后我使用以下命令将其编译为一个名为apiwrapper.o的目标文件:

g++ -L../include/libs -lapinameapi -shared -fPIC -c -D_LINUX_X86_64 -lpthread -lz -lm -lcrypto -lbz2 -I../include -DPROVIDE_LOG_UTILITIES -DTARGET_PLATFORM_LINUX c_api.cpp -o lapiwrapper.o -lrt

其中apinameapi是API提供程序的共享库。这很好。然后,我使用以下方法生成库文件:

ar rc libapiwrapper.a apiwrapper.o

再次,这很好。

现在我创建我的C文件(mycode.c),其中包含:

#include "mycode.h" #include <stdio.h> #include <string.h> #include <time.h> #ifdef _WIN32 #include <Windows.h> #else #include <unistd.h> #endif int connectToApi() { // Init API rc = apiname_api_init("programname"); }

头文件mycode.h包含:

#include <stdbool.h> #include <stdint.h> #include "c_api.h"

(显然还有其他内容,但为简洁起见,我省略了。)>

因此,我使用以下命令编译主程序:

gcc -Linclude/libs -lapiwrapper -shared -DKXVER=3 -fPIC -D_LINUX_X86_64 -lpthread -lz -lm -lcrypto -lbz2 -Iinclude -DPROVIDE_LOG_UTILITIES -DTARGET_PLATFORM_LINUX src/mycode.c -o lib/mycode.so -lrt -Wno-discarded-qualifiers -Wno-incompatible-pointer-types

也可以。然后,我运行程序(该特定文件由另一段代码加载),然后得到

undefined symbol: apiname_api_init

似乎在库文件中找不到该函数。我要去哪里错了?这是我第一次构建库,所以它可能是相当基本的东西。

编辑:我认为问题可能出在最终编译(创建mycode.so)正在生成共享对象文件这一事实上,而我需要该文件单独运行(不需要将生成的库文件以及)。我必须从另一个程序运行最终对象,因此它必须是独立的。有没有一种方法可以将其链接在一起,将所有内容“捆绑”到一个最终的so文件中?

我正在尝试创建一个静态库,以允许我在C程序中使用C ++ API。首先,我正在尝试调用一个名为APIName :: Api_init();的API函数。到目前为止,我已经创建了一个“包装器” ...

c++ c gcc ld dynamic-linking
3个回答
1
投票
命令ar rc libapiwrapper.a apiwrapper.o创建一个静态库。如果与之链接,则还需要链接其依赖关系。您需要创建一个共享库(.so文件)。您可能需要这样的操作(我已在单个命令中拆分了编译和链接步骤):

g++ -lapinameapi -c -D_LINUX_X86_64 -I../include -DPROVIDE_LOG_UTILITIES -DTARGET_PLATFORM_LINUX c_api.cpp -o lapiwrapper.o g++ -shared -fPIC -o libapiwrapper.so lapiwrapper.o -L../include/libs -lpthread -lz -lm -lcrypto -lbz2 -lrt


0
投票
我试图使用libssllibcrypto重现该问题。因此,就我而言,我需要产生一个使用api_wrapperlibssl函数的libcrypto,它应该是独立的。但是不幸的是,正如您在EDIT中要求的那样,两个或多个共享库无法捆绑在一起。请参考此链接Merge multiple .so shared libraries。如果您所谓的different, specialist language也能够加载静态库,则可以按以下步骤进行。

0
投票
您需要使用与标头相同的方式来终止CPP文件的“ C”操作;否则,方法名称将在对象中变形。

#ifdef __cplusplus extern "C" { #endif int apiname_api_init(char const * user_app_name) { return to_return_code(APIName::Api_init(user_app_name)); } void apiname_api_shutdown() { return APIName::api_shutdown(); } #ifdef __cplusplus } #endif

© www.soinside.com 2019 - 2024. All rights reserved.