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;

我尝试的另一种方法是使用 --wrapld 选项,但这不会更改导出的名称。使用以下代码传递 --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 (将#修改为@)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...