混合 C 和 C++ 的库/链接器问题
Posted
技术标签:
【中文标题】混合 C 和 C++ 的库/链接器问题【英文标题】:Library/linker problems mixing C and C++ 【发布时间】:2016-01-17 19:53:48 【问题描述】:我一直在为通用应用程序编写一些 C 和 C++ 基础架构。目前它正在进行中,包括使用 Lua 进行配置解析、日志记录功能和使用我自己的网络协议/消息传递 API 的客户端/服务器 API。
我已将代码组织到两个库中:一个用于 C 代码 (libmarlin.so),另一个用于 C++ 代码 (libmarlin++.so)。我使用两个而不是一个的原因是我在 C++ 库中仍然存在的原始问题:将应用程序链接到它会导致 Lua 代码或我的 C 库中的代码加上一些“未定义引用”错误其他随机 C++“operator new”引用,具体取决于 Makefile 中 -l
开关的顺序。我找不到满足依赖关系的组合。我已经了解订购这些开关的重要性,并根据本网站上的问题尝试了建议;都无济于事。
我将在此处粘贴我认为相关的内容,以节省复制大量代码的时间。如果您需要其他任何内容,请询问或克隆我的 GitHub 存储库:https://github.com/adamd1008/marlin。您需要将 Lua 代码放在 repo 外部名为 lua-5.3.2
的文件夹中,或根据需要更改 Makefile。另请注意,我修改了 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 库(尽管我不确定它在构建一个动态库?)。
任何指针将不胜感激。
【问题讨论】:
【参考方案1】:您的 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
第三个是费时的说明,基本上,将extern "C"
添加到 C 标头中的任何声明。
可能还有其他问题,但是,我会先试试这个。
【讨论】:
天哪,是的,我错过了一个 :( 通常我不会错过任何标题,谢谢。 @Doddy 很高兴能帮上忙 :)【参考方案2】:如果您想在您的 C++ 程序中使用 C 代码,您应该将所有 C 原型声明为extern "C"
。因此,请尝试像这样将所有 Lua 包含在您的程序中:
extern "C"
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
【讨论】:
同样应该由#include <lua.hpp>
完成(至少lua 5.1、5.2和5.3)以上是关于混合 C 和 C++ 的库/链接器问题的主要内容,如果未能解决你的问题,请参考以下文章
链接器错误,使用 g++ 链接到由 gcc 编译的库,未定义对该函数的引用