【问题标题】:import function from .so从 .so 导入函数
【发布时间】:2017-12-15 12:37:47
【问题描述】:

我需要从带有 boost.dll 库的 Linux .so 库中导入一个函数。我的代码是这样的:

namespace n1 {
    namespace n2 {
        struct st {
            std::string n;
            int m;
        }
    }
}

void foo(std::string const&, n1::n2::st& attr) {
    /*some implementation*/
}

这里我尝试导入函数foo()

int main(int argc, char** argv) {
    boost::filesystem::path path("some path");
    boost::dll::experimental::smart_library lib(path);
    auto f2 = lib.get_function<void(std::string const&, n1::n2::st&)>(path, "n1::n2::foo");  //<<----here runtime error
    f2( std::string(), st{});
}

但我收到此运行时错误:

在抛出 'boost::exception_detail::clone_impl >' 的实例后调用终止 what(): boost::dll::shared_library::get() failed (dlerror system message: /path_to_my_library.so: undefined symbol: n1::n2::foo): Illegal seek

【问题讨论】:

  • 嗯?您是否在定义 main() 的翻译单元中包含了标头,或者让编译器知道在这些命名空间中声明了 st?您似乎混淆了从 DLL 导入符号与编译使用这些符号及其依赖项的代码。即使您可以从 DLL 中导入函数,也不会自动为您声明它所依赖的所有符号。
  • @underscore_d,我必须使用 -I(要包含的路径)编译并包含包含实现 st 的头文件?
  • 如果您引用st 之类的符号,引用它的翻译单元需要通过声明可用来了解它。就这么简单。
  • @underscore_d,谢谢
  • 从发布的代码中我看到 n1::n2::st 是一种类型,而您可以从 dll 导入实例(通常是函数指针,但也可以是变量)。从问题描述中我得到的印象是您希望导入一个类型,但事实并非如此。

标签: c++ boost dllimport


【解决方案1】:

因为n1::n2::foo 不是与 C 兼容的导出名称,我建议您需要使用损坏的名称,或者使用 mangled_import

注意:此功能是实验性的

在我的编译器上

foo(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, n1::n2::st&)

改成

_Z3fooRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERN2n12n22stE

关于导入结构体的话题,请参阅Class Imports

更新

基于手动修改方法的工作示例:

  1. shared.cpp

    #include "shared.h"
    #include <iostream>
    
    void foo(std::string const& msg, n1::n2::st& attr) {
        std::cout << msg << " from " << __FILE__ << ":" << __LINE__ << " (" << __PRETTY_FUNCTION__ << ")\n";
        std::cout << "attr.m = " << attr.m << "\n";
        std::cout << "attr.n = " << attr.n << "\n";
    }
    
  2. shared.h

    #include <string>
    namespace n1 { namespace n2 { struct st { std::string n; int m; }; } }
    
  3. main.cpp

    #include <boost/dll.hpp>
    #include <boost/dll/smart_library.hpp>
    #include <boost/dll/import_mangled.hpp>
    #include <boost/exception/diagnostic_information.hpp>
    #include <iostream>
    
    #include "shared.h"
    
    int main() {
        boost::filesystem::path path("./libshared.so");
        try {
            boost::dll::experimental::smart_library lib(path);
            //auto f1 = boost::dll::experimental::import_mangled<void(std::string const&, n1::n2::st&)>(path, "foo");
            auto f1 = boost::dll::import<void(std::string const&, n1::n2::st&)>(path, "_Z3fooRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERN2n12n22stE");
    
            n1::n2::st arg { "world", 42 };
            f1("hello", arg);
    
        } catch(boost::exception const& e) {
            std::cout << boost::diagnostic_information(e, true) << '\n';
        }
    }
    

Live On Coliru

编译:

g++ -std=c++14 -shared -fPIC shared.cpp -o libshared.so
g++ -std=c++14 main.cpp -ldl -lboost_system -lboost_filesystem

显示错位的名字
nm libshared.so

运行演示

./a.out

打印

hello from shared.cpp:5 (void foo(const string&, n1::n2::st&))
attr.m = 42
attr.n = world

【讨论】:

  • 带有experimental::import_mangling runtine 类似的错误...请问,你能写出例子吗?
  • 啊。那么,您遇到了 相同 错误,而不仅仅是“相似”错误?
  • @underscore_d,运行时错误:“在抛出 'boost::exception_detail::clone_impl >' 的实例后调用终止 what(): boost::dll::shared_library::get() 失败( dlerror 系统消息:/path_to_my_library.so: undefined symbol: n1::n2::foo): Illegal seek"
  • @xperious 我使用手动修改添加了一个工作示例Live On Coliru。实验性的import_mangled 还没有为我工作。也许我用错了:)
  • 什么意思?
猜你喜欢
  • 1970-01-01
  • 2012-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-07
  • 2023-04-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多