c – 为什么在dlopen’d函数内传递std :: any的std :: any_cast
我正在玩c 17和插件,我遇到了一个我无法解决的错误.在下面的MWE中,我可以调用一个带有std :: any的本地函数,当我尝试读取内容时,一切都按预期工作.当我通过插件(dlopen)加载这个完全相同的函数时,它正确地看到了any上的类型,但它不能std :: any_cast内容.
在弄清楚导致此错误的原因时,将非常感谢任何帮助. 这是我的环境,MWE和产生的错误.
g++ (GCC) 7.1.1 20170526 (Red Hat 7.1.1-2) Copyright (C) 2017 Free Software Foundation,Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
SCons by Steven Knight et al.: script: v2.5.1.rel_2.5.1:3735:9dc6cee5c168[MODIFIED],2016/11/03 14:02:02,by bdbaddog on mongodog engine: v2.5.1.rel_2.5.1:3735:9dc6cee5c168[MODIFIED],by bdbaddog on mongodog engine path: ['/usr/lib/scons/SCons'] Copyright (c) 2001 - 2016 The SCons Foundation
. ├── SConstruct └── src ├── main.cpp ├── plugin.cpp └── SConscript 1 directory,4 files
SConscript('src/SConscript',variant_dir='build',duplicate=0)
env = Environment() env.Append(CXXFLAGS=['-std=c++17']) plugin = env.SharedLibrary('plugin','plugin.cpp') Install('../lib',plugin) driver_env = env.Clone() driver_env.Append(LIBS=['dl','stdc++fs']) driver = driver_env.Program('driver','main.cpp') Install('../bin',driver)
#include <any> #include <iostream> using namespace std; extern "C" { int plugin(any& context) { cout << " Inside Plugin" << endl; cout << " Has Value? " << context.has_value() << endl; cout << " Type Name: " << context.type().name() << endl; cout << " Value: " << any_cast<double>(context) << endl; } }
#include <functional> #include <iostream> #include <stdexcept> #include <any> #include <experimental/filesystem> #include <dlfcn.h> using namespace std; using namespace std::experimental; function< void(any&) > loadplugin(string filename) { function< void(any&) > plugin; filesystem::path library_path(filename); filesystem::path library_abspath = canonical(library_path); void * libraryHandle = dlopen(library_abspath.c_str(),RTLD_NOW); if (!libraryHandle) { throw runtime_error("ERROR: Could not load the library"); } plugin = (int(*) (any&))dlsym(libraryHandle,"plugin"); if (!plugin) { throw runtime_error("ERROR: Could not load the plugin"); } return plugin; } int local(any& context) { cout << " Inside Local" << endl; cout << " Has Value? " << context.has_value() << endl; cout << " Type Name: " << context.type().name() << endl; cout << " Value: " << any_cast<double>(context) << endl; } int main(int argc,char* argv[]) { cout << " Resolving Paths..." << endl; filesystem::path full_path = filesystem::system_complete( argv[0] ).parent_path(); filesystem::path plugin_path(full_path/".."/"lib"/"libplugin.so"); cout << " Creating Context..." << endl; any context(.1); cout << " Loading Plugin..." << endl; function<void(any&) > plugin = loadplugin(plugin_path.string()); cout << " Calling Local..." << endl; local(context); cout << " Calling Plugin..." << endl; plugin(context); }
scons: Reading SConscript files ... scons: done reading SConscript files. scons: Building targets ... g++ -o build/main.o -c -std=c++17 src/main.cpp g++ -o build/driver build/main.o -ldl -lstdc++fs Install file: "build/driver" as "bin/driver" g++ -o build/plugin.os -c -std=c++17 -fPIC src/plugin.cpp g++ -o build/libplugin.so -shared build/plugin.os Install file: "build/libplugin.so" as "lib/libplugin.so" scons: done building targets.
. ├── bin │?? └── driver ├── build │?? ├── driver │?? ├── libplugin.so │?? ├── main.o │?? └── plugin.os ├── lib │?? └── libplugin.so ├── SConstruct └── src ├── main.cpp ├── plugin.cpp └── SConscript 4 directories,10 files
Resolving Paths... Creating Context... Loading Plugin... Calling Local... Inside Local Has Value? 1 Type Name: d Value: 0.1 Calling Plugin... Inside Plugin Has Value? 1 Type Name: d terminate called after throwing an instance of 'std::bad_any_cast' what(): bad any_cast Value: Aborted (core dumped) 解决方法
libstdc的任何依赖于同一模板实例化的地址在程序中是相同的,这意味着你需要
take precautions if you are using
dlopen :
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |