C++ boost::di结合Boost.dll动态加载的依赖注入绑定报错问题
问题概述
联合使用C++依赖注入库boost::di与动态库加载库Boost.dll开发时触发编译错误,验证流程拆分为两个环节:
- 动态库加载功能测试
- 抽象类与动态加载实现类的依赖注入绑定
目前动态库加载功能已验证可正常运行,编写DI绑定逻辑时触发类模板期望类型参数但未收到对应类型的编译错误。
项目文件逻辑
ioperation.hpp:定义抽象接口ioperation,声明name() const、calculate(float x, float y)纯虚方法与虚析构函数sum.cpp:编译为libsum.so动态库,实现sum类继承ioperation接口,通过BOOST_DLL_ALIAS宏导出无参工厂方法create_sum用于创建类实例dot_product.cpp:编译为libdot_product.so动态库,实现dot_product类继承ioperation接口,类依赖ioperation类型指针完成点积计算,通过BOOST_DLL_ALIAS宏导出接收ioperation指针参数的工厂方法create_dot_productapplication_main.cpp:未使用DI的测试代码,可正常编译运行:通过boost::dll::import_alias导入两个动态库的工厂方法,创建实例后调用calculate方法,输出结果符合预期application_di.cpp:使用boost::di的业务代码,先通过Boost.dll导入两个库的工厂方法,提前创建sum_ptr、dot_product_ptr两个boost::shared_ptr<ioperation>类型实例指针;在通过di::make_injector构建注入器、绑定ioperation接口的lambda逻辑中,错误将变量名sum_ptr、dot_product_ptr作为模板参数传入boost::shared_ptr,触发编译错误
报错信息
在lambda函数内调用
injector.template create<boost::shared_ptr<sum_ptr>>()与injector.template create<boost::shared_ptr<dot_product_ptr>>()时,编译器提示boost::shared_ptr模板参数期望传入类型,但实际传入了变量sum_ptr、dot_product_ptr,编译失败。
错误根因
C++模板参数要求传入编译期可确定的类型/常量,sum_ptr、dot_product_ptr是运行时创建的实例变量,本身不是类型,不能作为模板参数传入尖括号内。
正确绑定方案
动态加载场景下,已经通过Boost.dll拿到的实例不需要再通过DI容器重新创建,直接将现成实例、动态导入的工厂绑定到注入器即可,参考实现如下:
// 1. 先完成动态库加载,导入导出的工厂方法 auto create_sum = boost::dll::import_alias<boost::shared_ptr<ioperation>()>( boost::filesystem::path("libsum.so"), "create_sum" ); auto create_dot_product = boost::dll::import_alias<boost::shared_ptr<ioperation>(ioperation*)>( boost::filesystem::path("libdot_product.so"), "create_dot_product" ); // 2. 构建DI注入器,完成接口绑定 auto injector = di::make_injector( // 绑定无依赖的sum实现:直接调用动态库导入的工厂返回实例 di::bind<ioperation>().named(di::type<sum>).to([&](){ return create_sum(); }), // 绑定有依赖的dot_product实现:从注入器解析依赖的ioperation实例,传入动态库工厂 di::bind<ioperation>().named(di::type<dot_product>).to([&](const auto& inj){ auto sum_op = inj.create<boost::shared_ptr<ioperation>>(di::named<sum>); return create_dot_product(sum_op.get()); }) ); // 3. 业务侧从注入器取实例使用 auto sum_op = injector.create<boost::shared_ptr<ioperation>>(di::named<sum>); auto dot_op = injector.create<boost::shared_ptr<ioperation>>(di::named<dot_product>);
注意事项
boost::di支持直接绑定运行时生成的现成实例、工厂函数,不需要强制所有实例都由DI容器完成构造- 同一抽象接口绑定多个实现时,使用
di::named做命名区分即可,禁止将运行时变量名写入模板尖括号 - 所有出现在模板尖括号
<>内的参数,必须是编译阶段就能确定的类型、常量表达式
内容的提问来源于stack exchange,提问作者Sukhdeep Singh
相关产品推荐
相关产品推荐

