混合 C 和 C++ 的库/链接器问题

Library/linker problems mixing C and C++

本文关键字:链接 问题 的库 C++ 混合      更新时间:2023-10-16

我一直在为通用应用程序编写一些C和C++基础设施。目前,它正在进行中,包括使用 Lua 进行配置解析、日志记录功能和使用我自己的网络协议/消息传递 API 的客户端/服务器 API。

我将代码组织到两个库中:一个用于 C 代码 (libmarlin.so),另一个用于C++代码 (libmarlin++.so)。顺便说一下,我有两个而不是一个的原因只是我仍然只使用 C++ 库的原始问题:将应用程序链接到它会导致 Lua 代码或我的 C 库中的代码出现"未定义的引用"错误,再加上一些其他随机C++"运算符新"引用,具体取决于 Makefile 中-l开关的顺序。我找不到满足依赖关系的组合。我已经了解这些开关订购的重要性,并根据本网站上的问题尝试了建议;一切都无济于事。

我将在此处粘贴我认为相关的内容,以节省复制大量代码。如果您需要其他任何内容,请询问或克隆我的GitHub存储库:https://github.com/adamd1008/marlin。你需要在存储库外部名为 lua-5.3.2 的文件夹中使用 Lua 代码,或者根据需要更改生成文件。另请注意,我修改了Lua makefile以构建动态库而不是默认的静态库,因此我在构建时使用-llua。(这实际上只是为了尝试解决根本问题。

汇编:

make -C src
make[1]: Entering directory `/home/adam/marlin/src'
** Compiling file 'log.c'
gcc -std=c99 -g -c -Wall -Wextra -Werror -rdynamic -fPIC -I../../lua-5.3.2/src -DMAJOR_VER=1 -DMINOR_VER=0 -DBUILD_VER=0 -DLOG_UUID="27dc17c4-bd53-11e5-bb37-a02bb831a7e4" log.c -o log.o
** Compiling file 'msg.c'
gcc -std=c99 -g -c -Wall -Wextra -Werror -rdynamic -fPIC -I../../lua-5.3.2/src -DMAJOR_VER=1 -DMINOR_VER=0 -DBUILD_VER=0 -DLOG_UUID="27dc17c4-bd53-11e5-bb37-a02bb831a7e4" msg.c -o msg.o
** Linking file 'libmarlin.so.1.0.0'
gcc -shared -Wl,-soname,libmarlin.so.1.0.0 -o ../lib/libmarlin.so.1.0.0 log.o msg.o
ln -sf libmarlin.so.1.0.0 ../lib/libmarlin.so
** Compiling file 'M_App.cpp'
g++ -std=c++11 -g -c -Wall -Wextra -Werror -rdynamic -fPIC -pedantic -I../../lua-5.3.2/src -DMAJOR_VER=1 -DMINOR_VER=0 -DBUILD_VER=0 M_App.cpp -o M_App.o
** Compiling file 'M_Field.cpp'
g++ -std=c++11 -g -c -Wall -Wextra -Werror -rdynamic -fPIC -pedantic -I../../lua-5.3.2/src -DMAJOR_VER=1 -DMINOR_VER=0 -DBUILD_VER=0 M_Field.cpp -o M_Field.o
** Compiling file 'M_FieldMap.cpp'
g++ -std=c++11 -g -c -Wall -Wextra -Werror -rdynamic -fPIC -pedantic -I../../lua-5.3.2/src -DMAJOR_VER=1 -DMINOR_VER=0 -DBUILD_VER=0 M_FieldMap.cpp -o M_FieldMap.o
** Compiling file 'M_Msg.cpp'
g++ -std=c++11 -g -c -Wall -Wextra -Werror -rdynamic -fPIC -pedantic -I../../lua-5.3.2/src -DMAJOR_VER=1 -DMINOR_VER=0 -DBUILD_VER=0 M_Msg.cpp -o M_Msg.o
** Compiling file 'M_MsgApp.cpp'
g++ -std=c++11 -g -c -Wall -Wextra -Werror -rdynamic -fPIC -pedantic -I../../lua-5.3.2/src -DMAJOR_VER=1 -DMINOR_VER=0 -DBUILD_VER=0 M_MsgApp.cpp -o M_MsgApp.o
** Linking file 'libmarlin++.so.1.0.0'
gcc -shared -L../../lua-5.3.2/src -llua -Wl,-soname,libmarlin++.so.1.0.0 -o ../lib/libmarlin++.so.1.0.0 M_App.o M_Field.o M_FieldMap.o M_Msg.o M_MsgApp.o
ln -sf libmarlin++.so.1.0.0 ../lib/libmarlin++.so
make -C test
make[2]: Entering directory `/home/adam/marlin/src/test'
** Compiling file 'msg_test.c'
gcc -std=c99 -g -c -Wall -Wextra -Werror -rdynamic -I../../../lua-5.3.2/src msg_test.c -o msg_test.o
** Linking file 'msg_test.o'
gcc -L../../lib -L../../../lua-5.3.2/src -lm -ldl -llua -lmarlin -o msg_test msg_test.o
** Compiling file 'app_test.cpp'
g++ -std=c++11 -g -c -Wall -Wextra -Werror -rdynamic -pedantic -I../../../lua-5.3.2/src app_test.cpp -o app_test.o
** Linking file 'app_test.o'
g++ -L../../lib -L../../../lua-5.3.2/src -lm -ldl -llua -lmarlin -lmarlin++ -o app_test app_test.o
../../lib/libmarlin++.so: undefined reference to `lua_tolstring(lua_State*, int, unsigned long*)'
../../lib/libmarlin++.so: undefined reference to `lua_type(lua_State*, int)'
../../lib/libmarlin++.so: undefined reference to `luaL_loadfilex(lua_State*, char const*, char const*)'
../../lib/libmarlin++.so: undefined reference to `lua_getglobal(lua_State*, char const*)'
../../lib/libmarlin++.so: undefined reference to `lua_geti(lua_State*, int, long long)'
../../lib/libmarlin++.so: undefined reference to `luaL_openlibs(lua_State*)'
../../lib/libmarlin++.so: undefined reference to `lua_typename(lua_State*, int)'
../../lib/libmarlin++.so: undefined reference to `lua_settop(lua_State*, int)'
../../lib/libmarlin++.so: undefined reference to `lua_close(lua_State*)'
../../lib/libmarlin++.so: undefined reference to `lua_pushstring(lua_State*, char const*)'
../../lib/libmarlin++.so: undefined reference to `lua_gettable(lua_State*, int)'
../../lib/libmarlin++.so: undefined reference to `luaL_newstate()'
collect2: error: ld returned 1 exit status
make[2]: *** [app_test] Error 1
make[2]: Leaving directory `/home/adam/marlin/src/test'
make[1]: *** [test] Error 2
make[1]: Leaving directory `/home/adam/marlin/src'
make: *** [all] Error 2

我怀疑有一个简单的解释,但我无法解决。根据最后一个编译步骤,-llua在我的任何一个库之前指定,但libmarlin++.so仍然存在问题,即使它本身也链接到Lua库(尽管我不确定它在构建动态库时是否有任何影响?

任何指示将不胜感激。

你的 Github 存储库中有很多代码,所以彻底的分析需要时间,但乍一看,这似乎是"失踪extern "C"的情况"(双关语)。

从C++代码中,当包含 C 标头时,您需要extern "C" .有几种方法可以做到这一点。首先,当包括时,例如:

extern "C" {
#include "the_c_header.h"
}

其次,在标题本身中:

#if defined(__cplusplus)
extern "C" {
#endif
.... contents of the C header...
#if defined(__cplusplus)
}
#endif
第三是耗时的,基本上

是向 C 标头中的任何声明添加extern "C"

可能还有其他问题,但是,我会先尝试一下。

如果你想

在C++程序中使用C代码,你应该将所有C原型声明为extern "C"。因此,请尝试像这样包装程序中的所有Lua包含的内容:

extern "C" {
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}