You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用含std::__1符号的闭源库函数遇链接错误,求解决方法

闭源库含std::__1::function参数的函数链接失败问题解决

问题背景

尝试调用闭源库libvendor.so中的函数,原工具链及头文件不可用。通过以下命令获取库信息:

$ file libvendor.so 
libvendor.so: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, BuildID[sha1]=ff, stripped

$ nm -CD libvendor.so | grep Start
0001ec3a T nm::vendor::className::Start(int, char const**, std::__1::function<void ()>)

自行编写的头文件header.h:

#include <functional>

namespace nm {
    namespace vendor {
        class className {
        public:
            static className* Get();
            void Start(int, char const**, std::function<void ()>);
        };
    }
}

main.cpp代码:

#include "header.h"

using namespace nm::vendor;
using namespace std;

std::function<void ()> startFunc;
void Start() {}

int main(void)
{
    className* c = className::Get();
    char const *str = "c style string";
    const char** str_ptr = &str;
    startFunc = Start;
    c->Start(1, str_ptr, startFunc);
}

使用crosstool-ng编译时出现链接错误:

$ ~/x-tools/arm-linux-gnueabihf/bin/arm-linux-gnueabihf-c++  --version
arm-linux-gnueabihf-c++ (crosstool-NG 1.25.0) 11.2.0

$ ~/x-tools/arm-linux-gnueabihf/bin/arm-linux-gnueabihf-c++ \
    -std=c++11 \
    -Wl,-v \
    -Wl,-rpath,. \
    -ldl \
    -mthumb-interwork \
    libvendor.so \
    -o main \
    main.cpp
collect2 version 11.2.0
~/x-tools/arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/11.2.0/../../../../arm-linux-gnueabihf/bin/ld -plugin ~/x-tools/arm-linux-gnueabihf/libexec/gcc/arm-linux-gnueabihf/11.2.0/liblto_plugin.so -plugin-opt=~/x-tools/arm-linux-gnueabihf/libexec/gcc/arm-linux-gnueabihf/11.2.0/lto-wrapper -plugin-opt=-fresolution=/tmp/cc35fC2k.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --sysroot=~/x-tools/arm-linux-gnueabihf/arm-linux-gnueabihf/sysroot --eh-frame-hdr -dynamic-linker /lib/ld-linux-armhf.so.3 -X -m armelf_linux_eabi -o main ~/x-tools/arm-linux-gnueabihf/arm-linux-gnueabihf/sysroot/usr/lib/crt1.o ~/x-tools/arm-linux-gnueabihf/arm-linux-gnueabihf/sysroot/usr/lib/crti.o ~/x-tools/arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/11.2.0/crtbegin.o -L~/x-tools/arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/11.2.0 -L~/x-tools/arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/11.2.0/../../../../arm-linux-gnueabihf/lib -L~/x-tools/arm-linux-gnueabihf/arm-linux-gnueabihf/sysroot/lib -L~/x-tools/arm-linux-gnueabihf/arm-linux-gnueabihf/sysroot/usr/lib -v -rpath . -rpath /system/vendor/sony/lib -rpath ~/nw-a50/myfirmware/bootimg/initrd_unpacked/lib/ -ldl libvendor.so /tmp/ccKaDp0K.o -lstdc++ -lm -lc -lgcc_s -lgcc -lc -lgcc_s -lgcc ~/x-tools/arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/11.2.0/crtend.o ~/x-tools/arm-linux-gnueabihf/arm-linux-gnueabihf/sysroot/usr/lib/crtn.o
GNU ld (crosstool-NG 1.25.0) 2.26.1
/tmp/ccSbQv2E.o: In function `main':
main.cpp:(.text+0x70): undefined reference to `nm::vendor::className::Start(int, char const**, std::function<void ()>)'
collect2: error: ld returned 1 exit status

尝试将头文件中声明改为std::__1::function时编译失败:

In file included from main.cpp:2:0:
header.h:84:57: error: 'std::__1' has not been declared
             void Start(int, char const**, std::__1::function<void ()>);

其他函数(如Get())可正常链接调用,需解决该链接问题。

核心原因

闭源库由LLVM/libc编译,其中std::function被放在内联命名空间__1中;而当前使用的GNU libstdc无此内联命名空间,导致代码生成的函数签名与库中符号不匹配,触发链接错误。

解决方法

方法1:切换到libc++编译

如果交叉工具链支持libc++,修改编译命令,指定使用libc替代libstdc,让编译环境与闭源库对齐:

~/x-tools/arm-linux-gnueabihf/bin/arm-linux-gnueabihf-c++ \
    -std=c++11 \
    -stdlib=libc++ \
    -Wl,-v \
    -Wl,-rpath,. \
    -ldl \
    -mthumb-interwork \
    libvendor.so \
    -o main \
    main.cpp

注意:若工具链未预编译libc++,需自行构建带libc++的交叉工具链。

方法2:手动映射内联命名空间

在头文件中手动定义std::__1命名空间,并导入std::function,让编译器生成匹配的符号:

#include <functional>

// 手动兼容libc++的内联命名空间__1
namespace std {
    namespace __1 {
        using ::std::function;
    }
}

namespace nm {
    namespace vendor {
        class className {
        public:
            static className* Get();
            void Start(int, char const**, std::__1::function<void ()>);
        };
    }
}

编译时会生成带std::__1::function的函数签名,与闭源库中的符号匹配,即可正常链接。

方法3:用函数指针替代std::function

如果无法修改标准库相关定义,可尝试用C风格函数指针替换std::function参数——多数情况下,std::function可兼容普通函数指针:

修改头文件:

namespace nm {
    namespace vendor {
        class className {
        public:
            static className* Get();
            void Start(int, char const**, void (*)());
        };
    }
}

修改main.cpp:

#include "header.h"

using namespace nm::vendor;

void Start() {}

int main(void)
{
    className* c = className::Get();
    char const *str = "c style string";
    const char** str_ptr = &str;
    c->Start(1, str_ptr, &Start);
}

此方法避免了标准库命名空间的差异问题,无需依赖std::function。

内容的提问来源于stack exchange,提问作者user1938027

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 10:22:04