如何解决C++中如何导入导出同名的不同函数
我正在为自定义语言编写运行时库,但在使其在 Linux 下工作时遇到了一些问题。 我需要创建一个共享对象文件,该文件导出运行时规范指定的符号。 其中一些名称与标准库冲突,一些是无效的 C++ 标识符。
在 Windows 上,我可以简单地将模块定义文件传递给 MSVC 链接器,但 ld
似乎没有提供等效的解决方案。我已经阅读了一些关于链接器脚本的内容,发现它们提供了类似的功能,但它们只解决了部分问题。它们允许我更改不是有效 C++ 标识符的导出名称,但会导致标准库名称冲突的新问题。
例如,行 exit = _ZN7runtime4exitEi;
也会导致 imported 符号被替换,这会在调用 exit
时导致无限递归,最终导致段错误(我猜是退出的一种方式)。
库源(runtime.cpp):
#include <cstdlib>
namespace runtime {
[[ noreturn ]] void __cdecl exit(int code) {
::exit(code);
}
// can't call this "not",because that's a keyword
int __cdecl bitwise_not(int a) {
return ~a;
}
// exported as "object::.ctor"
void __cdecl object_ctor(runtime::object* instance) {
// empty
}
}
MSVC 模块定义(exports64.def):
LIBRARY runtime
EXPORTS
exit=?exit@runtime@@YAXH@Z
not=?bitwise_not@runtime@@YAHH@Z
object::.ctor=?object_ctor@runtime@@YAXPEAUobject@1@@Z
链接脚本(libruntime64.map):
exit = _ZN7runtime4exitEi;
not = _ZN7runtime11bitwise_notEi
object::.ctor = _ZN7runtime11object_ctorEPNS_6objectE;
/* use the default linker script */
SECTIONS { } INSERT AFTER .text;
我尝试的另一种方法是使用 --wrap
的 ld
选项,但这不会更改导出的名称。使用以下代码传递 --wrap=exit
会将 __real_exit
正确解析为导入的 exit
函数,但导出的名称仍为 __wrap_exit
。
namespace runtime {
extern "C" [[ noreturn ]] void __real_exit(int code);
extern "C" [[ noreturn ]] void __wrap_exit(int code) {
__real_exit(code);
}
}
所以我想我的问题的核心是这样的:如何链接一个导入和导出两个同名不同符号的共享对象文件?
如果这是相关的,我使用的前端是 Clang,完整的命令行如下所示:
clang -Wl,--script=runtime/libruntime64.map \
-lstdc++ -lm -std=c++17 \
-fpic -shared -Wl,-verbose \
-o out/libruntime.so runtime/*.cpp
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。