我无法使用C ++依赖注入库“ boost :: di “与另一个boost库一起用于名为“ boost.dll ”。
我将问题分为两个部分 - 首先,测试动态加载,其次将抽象类结合到实现(动态加载)。
我能够动态地成功加载库。但是,当我试图使用依赖注入绑定时,就报告了不匹配的班级模板是预期的且未收到的。
我在此存储库中有一个非常基本的示例代码:
我真的会使用一些帮助来找出绑定过程动态加载的库。 (请参阅底部的确切错误)
-
文件 ioperation.hpp
#include< string>
类ioperation {
民众:
虚拟std :: string name()const = 0;
虚拟浮点计算(float x,float y)= 0;
虚拟〜Ioperation(){}
};
-
文件 sum.cpp
#include< boost/config.hpp>
#include< boost/dll/alias.hpp>
#include< boost/dll/import.hpp>
#include“ ioperation.hpp”
#include< iostream>
名称空间sum_namespace {
班级总和:公共ioperation {
民众:
sum(){
std :: cout<< “ [sum_constructor]”<< std :: endl;
}
std :: string name()const {
返回“总和”;
}
float计算(float x,float y){
返回x + y;
}
〜sum(){
std :: cout<< “ [〜sum_destructor]”<< std :: endl;
}
//工厂方法
静态boost :: shared_ptr< sum> create_sum(){
返回boost :: shared_ptr< sum>(
新sum()
);
}
};
}
BOOST_DLL_ALIAS(
sum_namespace :: sum :: create_sum,//< - 此函数由...导出...
create_sum //< - ...这个别名名称
)
-
文件 dot_product.cpp
#include< boost/config.hpp>
#include< boost/dll/alias.hpp>
#include< boost/dll/import.hpp>
#include< iostream>
#include“ ioperation.hpp”
命名空间dot_product_namespace {
类dot_product:public ioperation {
boost :: shared_ptr< ioperation> sum_ptr;
民众:
dot_product(boost :: shared_ptr< ioperation>& arg){
sum_ptr = arg;
std :: cout<< “ [dot_product_constructor]”<< std :: endl;
}
std::string name() const {
return "dot_product";
}
float calculate(float a1, float a2) {
//与给定矢量的点产品
//公式:AB = A1*B1 + A2*B2
返回sum_ptr->计算(a1*a1,a2*a2);
}
//工厂方法
静态boost :: shared_ptr< ioperation> create_dot_product(boost :: shared_ptr< ioperation> sum_ptr){
返回boost :: shared_ptr< ioperation>(
新的dot_product(sum_ptr)
);
}
〜DOT_PRODUCT(){
std :: cout<< “ [〜DOT_PRODUCT_DESTRUCTOR]”<< std :: endl;
}
};
};
BOOST_DLL_ALIAS(
dot_product_namespace :: dot_product :: create_dot_product,//&lt ;--此函数由...导出...
create_dot_product //< - ...此别名名称
)
-
文件 application_di.cpp
#include“ boost/shared_ptr.hpp”
#include< boost/dll/import.hpp>
#include“ boost/function.hpp”
#include< boost/di.hpp>
#include“ ioperation.hpp”
#include< iostream>
命名空间di = boost :: di;
命名空间dll = boost :: dll;
类应用程序{
私人的:
boost::shared_ptr ptr_;
民众:
app(boost :: shared_ptr< ioperation> ptr)
:ptr_(ptr)
{
std :: cout<<“名称:”<< ptr _--> name()<< std :: endl;
}
};
int main(int argc,char* argv []){
//设置通往库(.so)文件的路径
boost :: fileSystem :: path path shared_library_path(“。”); // ARGV [1]包含使用我们的插件库的目录路径
boost :: filesystem :: path child_library_path = shared_library_path/“ dot_product”;
boost :: filesystem :: path parth parent_library_path = shared_library_path/“ sum”;
//定义LIB构造函数的功能类型
typedef boost :: shared_ptr< ioperation> (sum_create_t)();
typedef boost :: shared_ptr< ioperation> (dot_product_create_t)(boost :: shared_ptr< ioperation>);
boost :: function< sum_create_t> sum_creator;
boost :: function< dot_product_create_t> dot_product_creator;
//导入总和lib构造函数(无需arg)
sum_creator = boost :: dll :: import_alias< sum_create_t>(//必须明确指定导入符号的类型
parent_library_path,//库的路径
“ create_sum”,//符号导入
dll :: load_mode :: append_decorations //请附加扩展和前缀
);
//导入dot_product lib构造函数(将PTR的1 arg归入ioperation)
dot_product_creator = boost :: dll :: import_alias< dot_product_create_t>(//必须明确指定导入符号的类型
child_library_path,//图书馆的路径
“ create_dot_product”,//符号导入
dll :: load_mode :: append_decorations //请附加扩展和前缀
);
//创建一个ptr到对象
boost :: shared_ptr< ioperation> sum_ptr = sum_creator();
//创建一个ptr到dot_product对象(传递在创建的总和对象ptr上方)
boost :: shared_ptr< ioperation> dot_product_ptr = dot_product_creator(sum_ptr);
auto use_sum = true;
const auto注射器= di :: make_injector(
di :: bind< ioperation>()。to([&](const auto& inextor) - > boost :: shared_ptr< ioperation> {
if(use_sum)
返回imptor.template create< boost :: shared_ptr< sum_ptr>>();
别的
return indector.template create< boost :: shared_ptr< dot_product_ptr>>();
}))
);
injector.create();
}
-
文件 application_main.cpp
#include“ boost/shared_ptr.hpp”
#include< boost/dll/import.hpp>
#include“ boost/function.hpp”
#include< iostream>
#include“ ioperation.hpp”
命名空间dll = boost :: dll;
int main(int argc,char* argv []){
//设置通往库(.so)文件的路径
boost :: filesystem :: path shared_library_path(argv [1]); // ARGV [1]包含使用我们的插件库的目录路径
boost :: filesystem :: path child_library_path = shared_library_path/“ dot_product”;
boost :: filesystem :: path parth parent_library_path = shared_library_path/“ sum”;
//定义LIB构造函数的功能类型
typedef boost :: shared_ptr< ioperation> (sum_create_t)();
typedef boost :: shared_ptr< ioperation> (dot_product_create_t)(boost :: shared_ptr< ioperation>);
boost :: function< sum_create_t> sum_creator;
boost :: function< dot_product_create_t> dot_product_creator;
//导入总和lib构造函数(无需arg)
sum_creator = boost :: dll :: import_alias< sum_create_t>(//必须明确指定导入符号的类型
parent_library_path,//库的路径
“ create_sum”,//符号导入
dll :: load_mode :: append_decorations //请附加扩展和前缀
);
//导入dot_product lib构造函数(将PTR的1 arg归入ioperation)
dot_product_creator = boost :: dll :: import_alias< dot_product_create_t>(//必须明确指定导入符号的类型
child_library_path,//图书馆的路径
“ create_dot_product”,//符号导入
dll :: load_mode :: append_decorations //请附加扩展和前缀
);
//创建PTR到Parent_plugin_sum objecti
boost :: shared_ptr< ioperation> sum_ptr = sum_creator();
//创建一个ptr到child_plugin_mult对象(传递在创建的parent_plugin_sum对象上方)
boost :: shared_ptr< ioperation> dot_product_ptr = dot_product_creator(sum_ptr);
//执行计算对象PTR的方法
std :: cout<< “插件名称:”<< sum_ptr-> name()<< std :: endl;
std :: cout<< “ sum_ptr->计算(1,2)[Expection = 3]:”<< sum_ptr->计算(1,2)<< std :: endl;
std :: cout&lt;&lt; "Plugin Name: " << dot_product_ptr-&gt; name()&lt;&lt; std :: endl;
std :: cout&lt;&lt; “ dot_product_ptr-&gt;计算(1,2)[Expection = 5]:”&lt;&lt; dot_product_ptr-&gt;计算(1,2)&lt;&lt; std :: endl;
}
以下是观察到的确切错误:
+ echo '=> Compiling libraries and application_main.cpp ...'
=> Compiling libraries and application_main.cpp ...
+ g++ -std=c++14 -fPIC -c -o libsum.o sum.cpp
+ g++ -shared -o libsum.so libsum.o
+ g++ -std=c++14 -fPIC -c -o libdot_product.o dot_product.cpp
+ g++ -shared -o libdot_product.so libdot_product.o
+ g++ -std=c++14 -lboost_filesystem -lboost_system -ldl application_main.cpp -o application_main
+ echo '=> Compilation completed. '
=> Compilation completed.
+ echo '=> Executing ./application_main .'
=> Executing ./application_main .
+ ./application_main .
[sum_constructor]
[dot_product_constructor]
Plugin Name: sum
sum_ptr->calculate(1, 2)[expected=3]: 3
Plugin Name: dot_product
dot_product_ptr->calculate(1, 2)[expected=5]: 5
[~dot_product_destructor]
[~sum_destructor]
+ echo ==================================
==================================
+ echo '=> Compiling application_di.cpp ...'
=> Compiling application_di.cpp …
+ g++ application_di.cpp -lboost_filesystem -lboost_system -ldl -o application_di
application_di.cpp: In lambda function:
application_di.cpp:62:65: error: type/value mismatch at argument 1 in template parameter list for ‘template<class T> class boost::shared_ptr’
62 | return injector.template create<boost::shared_ptr<sum_ptr>>();
| ^~~~~~~
application_di.cpp:62:65: note: expected a type, got ‘sum_ptr’
application_di.cpp:64:65: error: type/value mismatch at argument 1 in template parameter list for ‘template<class T> class boost::shared_ptr’
64 | return injector.template create<boost::shared_ptr<dot_product_ptr>>();
| ^~~~~~~~~~~~~~~
application_di.cpp:64:65: note: expected a type, got ‘dot_product_ptr’
I am unable to use C++ dependency injection library "boost::di" with another boost library for dynamic loading of libraries named "Boost.dll".
I broke down the problem into two parts - firstly, Testing dynamic loading, and secondly, binding the abstract class to implementation (which is loaded dynamically).
I am able to successfully load the libraries dynamically. But when I am trying to use Dependency injection binding then It is reporting the mismatch that class template is expected and not received.
I have a very basic sample code in this repo:
https://bitbucket.org/kobe_la/boost-plugins-prework/src/master/
I would really use some help in figuring out the binding process for dynamically loaded library. (see exact error at bottom)
-
File ioperation.hpp
#include <string>
class ioperation {
public:
virtual std::string name() const = 0;
virtual float calculate(float x, float y) = 0;
virtual ~ioperation() {}
};
-
File sum.cpp
#include <boost/config.hpp>
#include <boost/dll/alias.hpp>
#include <boost/dll/import.hpp>
#include "ioperation.hpp"
#include <iostream>
namespace sum_namespace {
class sum: public ioperation {
public:
sum() {
std::cout << "[sum_constructor]" << std::endl;
}
std::string name() const {
return "sum";
}
float calculate(float x, float y) {
return x + y;
}
~sum() {
std::cout << "[~sum_destructor]" << std::endl;
}
// Factory method
static boost::shared_ptr<sum> create_sum() {
return boost::shared_ptr<sum>(
new sum()
);
}
};
}
BOOST_DLL_ALIAS(
sum_namespace::sum::create_sum, // <-- this function is exported with...
create_sum // <-- ...this alias name
)
-
File dot_product.cpp
#include <boost/config.hpp>
#include <boost/dll/alias.hpp>
#include <boost/dll/import.hpp>
#include <iostream>
#include "ioperation.hpp"
namespace dot_product_namespace {
class dot_product: public ioperation {
boost::shared_ptr<ioperation> sum_ptr;
public:
dot_product(boost::shared_ptr<ioperation> &arg) {
sum_ptr = arg;
std::cout << "[dot_product_constructor]" << std::endl;
}
std::string name() const {
return "dot_product";
}
float calculate(float a1, float a2) {
//dot product given vector with itself
//formula: a.b = a1*b1 + a2*b2
return sum_ptr->calculate(a1*a1, a2*a2);
}
// Factory method
static boost::shared_ptr<ioperation> create_dot_product(boost::shared_ptr<ioperation> sum_ptr) {
return boost::shared_ptr<ioperation>(
new dot_product(sum_ptr)
);
}
~dot_product() {
std::cout << "[~dot_product_destructor]" << std::endl;
}
};
};
BOOST_DLL_ALIAS(
dot_product_namespace::dot_product::create_dot_product, // <-- this function is exported with...
create_dot_product // <-- ...this alias name
)
-
File application_di.cpp
#include "boost/shared_ptr.hpp"
#include <boost/dll/import.hpp>
#include "boost/function.hpp"
#include <boost/di.hpp>
#include "ioperation.hpp"
#include <iostream>
namespace di = boost::di;
namespace dll = boost::dll;
class app {
private:
boost::shared_ptr<ioperation> ptr_;
public:
app(boost::shared_ptr<ioperation> ptr)
: ptr_(ptr)
{
std::cout<<"name: " << ptr_->name()<<std::endl;
}
};
int main(int argc, char* argv[]) {
//setting up paths to library(.so) files
boost::filesystem::path shared_library_path("."); // argv[1] contains path to directory with our plugin library
boost::filesystem::path child_library_path = shared_library_path/"dot_product";
boost::filesystem::path parent_library_path = shared_library_path/"sum";
//defining function types for lib constructors
typedef boost::shared_ptr<ioperation> (sum_create_t)();
typedef boost::shared_ptr<ioperation> (dot_product_create_t)(boost::shared_ptr<ioperation>);
boost::function<sum_create_t> sum_creator;
boost::function<dot_product_create_t> dot_product_creator;
//importing SUM lib constructor(takes no arg)
sum_creator = boost::dll::import_alias<sum_create_t>( // type of imported symbol must be explicitly specified
parent_library_path, // path to library
"create_sum", // symbol to import
dll::load_mode::append_decorations // do append extensions and prefixes
);
//importing DOT_PRODUCT lib constructor(takes 1 arg of ptr to IOPERATION)
dot_product_creator = boost::dll::import_alias<dot_product_create_t>( // type of imported symbol must be explicitly specified
child_library_path, // path to library
"create_dot_product", // symbol to import
dll::load_mode::append_decorations // do append extensions and prefixes
);
//creating a ptr to SUM object
boost::shared_ptr<ioperation> sum_ptr = sum_creator();
//creating a ptr to DOT_PRODUCT object(passing above created SUM object ptr)
boost::shared_ptr<ioperation> dot_product_ptr = dot_product_creator(sum_ptr);
auto use_sum = true;
const auto injector = di::make_injector(
di::bind<ioperation>().to([&](const auto& injector) -> boost::shared_ptr<ioperation> {
if (use_sum)
return injector.template create<boost::shared_ptr<sum_ptr>>();
else
return injector.template create<boost::shared_ptr<dot_product_ptr>>();
})
);
injector.create<app>();
}
-
File application_main.cpp
#include "boost/shared_ptr.hpp"
#include <boost/dll/import.hpp>
#include "boost/function.hpp"
#include <iostream>
#include "ioperation.hpp"
namespace dll = boost::dll;
int main(int argc, char* argv[]) {
//setting up paths to library(.so) files
boost::filesystem::path shared_library_path(argv[1]); // argv[1] contains path to directory with our plugin library
boost::filesystem::path child_library_path = shared_library_path/"dot_product";
boost::filesystem::path parent_library_path = shared_library_path/"sum";
//defining function types for lib constructors
typedef boost::shared_ptr<ioperation> (sum_create_t)();
typedef boost::shared_ptr<ioperation> (dot_product_create_t)(boost::shared_ptr<ioperation>);
boost::function<sum_create_t> sum_creator;
boost::function<dot_product_create_t> dot_product_creator;
//importing SUM lib constructor(takes no arg)
sum_creator = boost::dll::import_alias<sum_create_t>( // type of imported symbol must be explicitly specified
parent_library_path, // path to library
"create_sum", // symbol to import
dll::load_mode::append_decorations // do append extensions and prefixes
);
//importing DOT_PRODUCT lib constructor(takes 1 arg of ptr to IOPERATION)
dot_product_creator = boost::dll::import_alias<dot_product_create_t>( // type of imported symbol must be explicitly specified
child_library_path, // path to library
"create_dot_product", // symbol to import
dll::load_mode::append_decorations // do append extensions and prefixes
);
//creating a ptr to PARENT_PLUGIN_SUM objecti
boost::shared_ptr<ioperation> sum_ptr = sum_creator();
//creating a ptr to CHILD_PLUGIN_MULT object(passing above created PARENT_PLUGIN_SUM object ptr)
boost::shared_ptr<ioperation> dot_product_ptr = dot_product_creator(sum_ptr);
//executing calculate methods for object ptrs
std::cout << "Plugin Name: " << sum_ptr->name() << std::endl;
std::cout << "sum_ptr->calculate(1, 2)[expected=3]: " << sum_ptr->calculate(1, 2) << std::endl;
std::cout << "Plugin Name: " << dot_product_ptr->name() << std::endl;
std::cout << "dot_product_ptr->calculate(1, 2)[expected=5]: " << dot_product_ptr->calculate(1, 2) << std::endl;
}
Below is the exact error observed:
+ echo '=> Compiling libraries and application_main.cpp ...'
=> Compiling libraries and application_main.cpp ...
+ g++ -std=c++14 -fPIC -c -o libsum.o sum.cpp
+ g++ -shared -o libsum.so libsum.o
+ g++ -std=c++14 -fPIC -c -o libdot_product.o dot_product.cpp
+ g++ -shared -o libdot_product.so libdot_product.o
+ g++ -std=c++14 -lboost_filesystem -lboost_system -ldl application_main.cpp -o application_main
+ echo '=> Compilation completed. '
=> Compilation completed.
+ echo '=> Executing ./application_main .'
=> Executing ./application_main .
+ ./application_main .
[sum_constructor]
[dot_product_constructor]
Plugin Name: sum
sum_ptr->calculate(1, 2)[expected=3]: 3
Plugin Name: dot_product
dot_product_ptr->calculate(1, 2)[expected=5]: 5
[~dot_product_destructor]
[~sum_destructor]
+ echo ==================================
==================================
+ echo '=> Compiling application_di.cpp ...'
=> Compiling application_di.cpp …
+ g++ application_di.cpp -lboost_filesystem -lboost_system -ldl -o application_di
application_di.cpp: In lambda function:
application_di.cpp:62:65: error: type/value mismatch at argument 1 in template parameter list for ‘template<class T> class boost::shared_ptr’
62 | return injector.template create<boost::shared_ptr<sum_ptr>>();
| ^~~~~~~
application_di.cpp:62:65: note: expected a type, got ‘sum_ptr’
application_di.cpp:64:65: error: type/value mismatch at argument 1 in template parameter list for ‘template<class T> class boost::shared_ptr’
64 | return injector.template create<boost::shared_ptr<dot_product_ptr>>();
| ^~~~~~~~~~~~~~~
application_di.cpp:64:65: note: expected a type, got ‘dot_product_ptr’
发布评论
评论(1)
共享指针是问题。
bind&lt;&gt;
模板参数不能是指针或参考类型我想出了一种工作方式来绑定依赖性:
完整演示
另请参见GitHub: https ://github.com/sehe/boost-plugins-prework
文件
ioperation.hpp
文件
sum.cpp
文件
sum.hpp
文件
dot_product.cpp
文件
dot_product.h
文件
application_di.cpp
文件
application_main.cpp
文件
compile_n_run.sh
使用
compile_n_run.sh
:或更多live:
Shared pointer is the problem. The
bind<>
template argument cannot be a pointer or reference typeI figured out a working way to bind the dependency:
Full Demo
See also Github: https://github.com/sehe/boost-plugins-prework
File
ioperation.hpp
File
sum.cpp
File
sum.hpp
File
dot_product.cpp
File
dot_product.h
File
application_di.cpp
File
application_main.cpp
File
compile_n_run.sh
Output
Using
compile_n_run.sh
:Or more live: