C++动态库加载的依赖注入

发布于 2025-02-13 10:05:49 字数 10099 浏览 0 评论 0 原文

我无法使用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’

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

请恋爱 2025-02-20 10:05:49

共享指针是问题。 bind&lt;&gt; 模板参数不能是指针或参考类型

有一些有关为什么在 bind&lt;&gt; 中禁止指针的信息: https://github.com/boost-ext/di/issues/317

我想出了一种工作方式来绑定依赖性:

const auto injector =
    di::make_injector(di::bind<ioperation>().to(
        [=, &use_sum](const auto& injector) -> op_ptr
        {
            return use_sum
                ? sum_creator()
                : dot_product_creator(sum_creator());
        }) //
    );

请注意,只要存在注射器,通过值捕获工厂功能就可以保持DLL。这比参考捕获更安全。
通过参考突出显示喷油器是动态的,捕获 use_sum 。如果不需要,那么我将用:

替换整个喷油器

  const auto inector = di :: make_injector(di :: bind&lt; ioperation&gt;()。
    use_sum? sum_creator():dot_product_creator(sum_creator())//
);
 

完整演示

另请参见GitHub: https ://github.com/sehe/boost-plugins-prework

  • 文件 ioperation.hpp

      #pragma一次
     #include&lt; boost/shared_ptr.hpp&gt;
     #include&lt; string&gt;
    
     结构ioperation {
       虚拟std :: string name()const = 0;
       虚拟浮点计算(float x,float y)= 0;
    
       Virtual〜ioperation()=默认值;
     };
    
     使用op_ptr = boost :: shared_ptr&lt; ioperation&gt;;
     
  • 文件 sum.cpp

      #include&lt; boost/config.hpp&gt;
     #include&lt; boost/dll/alias.hpp&gt;
     #include&lt; boost/dll/import.hpp&gt;
     #include“ ioperation.hpp”
     #include&lt; iostream&gt;
    
     名称空间sum_namespace {
         班级总和:公共ioperation {
           民众:
             sum(){std :: cout&lt;&lt; “ [sum_constructor]”&lt;&lt; std :: endl; }
             std :: string name()const {返回“ sum”; }
             float计算(float x,float y){返回x + y; }
             〜sum(){std :: cout&lt;&lt; “ [〜sum_destructor]”&lt;&lt; std :: endl; }
    
             //工厂方法
             static op_ptr create_sum(){return op_ptr(new sum()); }
         };
     } //名称空间sum_namespace
    
     BOOST_DLL_ALIAS(
         sum_namespace :: sum :: create_sum,//&lt;  - 此函数由...导出...
         create_sum //&lt;  -  ...这个别名名称
     )
     
  • 文件 sum.hpp

      #pragma一次
     #include“ ioperation.hpp”
     #include“ ioperation.hpp”
    
     名称空间sum_namespace {
         结构总和:ioperation {
             和();
             〜sum()覆盖;
             std :: string name()const覆盖;
             浮点计算(浮动,浮点)覆盖;
    
             static op_ptr create_sum();
         };
     } //名称空间sum_namespace
     
  • 文件 dot_product.cpp

      #include“ dot_product.h”
     #include&lt; boost/config.hpp&gt;
     #include&lt; boost/dll/alias.hpp&gt;
     #include&lt; boost/dll/import.hpp&gt;
     #include&lt; iostream&gt;
    
     命名空间dot_product_namespace {
    
         dot_product :: dot_product(op_ptr&amp; arg){
             sum_ptr = arg;
             std :: cout&lt;&lt; “ [dot_product_constructor]”&lt;&lt; std :: endl;
         }
    
         std :: String dot_product :: name()const {返回“ dot_product”; }
    
         float dot_product ::计算(float a1,float a2){
             //与给定矢量的点产品
             //公式:AB = A1*B1 + A2*B2
             返回sum_ptr-&gt;计算(a1 * a1,a2 * a2);
         }
    
         //工厂方法
         /*static*/ op_ptr dot_product :: create_dot_product(op_ptr sum_ptr){
             return op_ptr(new Dot_product(sum_ptr));
         }
    
         dot_product :: 〜dot_product(){
             std :: cout&lt;&lt; “ [〜DOT_PRODUCT_DESTRUCTOR]”&lt;&lt; std :: endl;
         }
     }; //名称空间dot_product_namespace
    
     BOOST_DLL_ALIAS(dot_product_namespace :: dot_product ::
                         create_dot_product,//&lt;  - 此功能由...导出
                     create_dot_product //&lt;  -  ...此别名名称
     )
     
  • 文件 dot_product.h

      #pragma一次
     #include“ ioperation.hpp”
    
     命名空间dot_product_namespace {
    
         struct dot_product:ioperation {
             dot_product(op_ptr&amp;);
             〜dot_product()覆盖;
             std :: string name()const覆盖;
             浮点计算(浮动,浮点)覆盖;
    
             static op_ptr create_dot_product(op_ptr sum_ptr);
    
           私人的:
             op_ptr sum_ptr;
         };
     }; //名称空间dot_product_namespace
     
  • 文件 application_di.cpp

      #include“ boost/function.hpp”
     #include“ ioperation.hpp”
     #include&lt; boost/di.hpp&gt;
     #include&lt; boost/dll/import.hpp&gt;
     #include&lt; iostream&gt;
    
     命名空间di = boost :: di;
     命名空间dll = boost :: dll;
    
     类应用程序{
      私人的:
        op_ptr ptr_;
    
      民众:
          app(boost :: shared_ptr&lt; ioperation&gt; ptr)
              :ptr_(ptr)
          {
              std :: cout&lt;&lt; “名称:”&lt;&lt; ptr _--&gt; name()&lt;&lt;&lt; std :: endl;
          }
     };
    
     使用boost :: filesystem :: path;
    
     int main(int argc,char ** argv){
         //设置通往库(.so)文件的路径
         路径lib_path(argc&gt; 1?argv [1]:“。”),
             child_library_path = lib_path /“ dot_product”,
             parent_library_path = lib_path /“ sum”;
    
         //定义LIB构造函数的功能类型
         使用sum_create_t = op_ptr();
         使用dot_product_create_t = op_ptr(op_ptr);
    
         //进口总和工厂
         auto sum_creator = boost :: dll :: import_alias&lt; sum_create_t&gt;(
             parent_library_path,
             “ create_sum”,
             dll :: load_mode :: append_decorations);
    
         //导入dot_product lib工厂
         auto dot_product_creator =
             boost :: dll :: import_alias&lt; dot_product_create_t&gt;(
                 child_library_path,
                 “ create_dot_product”,
                 dll :: load_mode :: append_decorations);
    
         auto use_sum = true;
    
         const auto注射器=
             di :: make_injector(di :: bind&lt; ioperation&gt;()。
                 [=,&amp; use_sum](const auto&amp;喷油器) - &gt; OP_PTR
                 {
                     返回use_sum
                         ? sum_creator()
                         :dot_product_creator(sum_creator());
                 })//
             );
    
         use_sum = argc&gt; 2;
         注射器。
     }
     
  • 文件 application_main.cpp

      #include“ boost/shared_ptr.hpp”
     #include&lt; boost/dll/import.hpp&gt;
     #include“ boost/function.hpp”
     #include&lt; iostream&gt;
     #include“ ioperation.hpp”
    
     命名空间dll = boost :: dll;
     使用boost :: filesystem :: path;
    
     int main(int argc,char ** argv)
     {
         //设置通往库(.so)文件的路径
         路径lib_path(argc&gt; 1?argv [1]:“。”),
             child_library_path = lib_path /“ dot_product”,
             parent_library_path = lib_path /“ sum”;
    
         //定义LIB构造函数的功能类型
         使用sum_create_t = op_ptr();
         使用dot_product_create_t = op_ptr(op_ptr);
    
         //进口总和工厂
         auto sum_creator = dll :: import_alias&lt; sum_create_t&gt;(
             parent_library_path,
             “ create_sum”,
             dll :: load_mode :: append_decorations);
    
         //导入dot_product lib工厂
         auto dot_product_creator =
             dll :: import_alias&lt; dot_product_create_t&gt;(
                 child_library_path,
                 “ create_dot_product”,
                 dll :: load_mode :: append_decorations);
    
         auto sum_ptr = sum_creator();
         auto dot_product_ptr = dot_product_creator(sum_ptr);
    
         //执行计算对象PTR的方法
         for(op_ptr op:{sum_creator(),dot_product_creator(sum_creator())}){
             std :: cout&lt;&lt; “ \ nplugin名称:”&lt;&lt; op-&gt; name()&lt;&lt; “ \ n”;
             std :: cout&lt;&lt; “计算(1,2):”&lt;&lt; op-&gt;计算(1,2)&lt;&lt;&lt; “ \ n”;
         }
     }
     
  • 文件 compile_n_run.sh

     #!/bin/bash
    
     设置-e -x -u
     ./cleanup.sh
    
     echo“ =&gt;现在编译...”
     cppflags =“  -  std = c ++ 14 -fpic -i/home/sehe/sehe/custom/boost -di/include/include/”
     ldflags =“”
    
     #在Sehe的机器上编译所需:
     #cppflags =“ $ cppflags -i/home/sehe/sehe/custom/boost -di/include/include/'
     #cppflags =“ $ cppflags -isystem/home/sehe/sehe/custom/superboost/”;
     #ldflags =“ $ ldflags -l/home/sehe/sehe/custom/superboost/stage/lib”
    
     g ++ $ cppflags sum.cpp -shared -o libsum.so $ ldflags
     g ++ $ cppflags dot_product.cpp -shared -o libdot_product.so $ ldflags
    
     #添加应用程序库
     ldflags =“ $ ldflags -lboost_filesystem -lboost_system -ldl”
     g ++ $ cppflags application_main.cpp -o application_main $ ldflags
     g ++ $ cppflags application_di.cpp -o application_di $ ldflags
    
     ./application_main。
    
     ./application_di。 use_sum
     ./application_di。 #使用dot_product
     

使用

compile_n_run.sh

+ ./cleanup.sh
removed 'application_main'
removed 'libdot_product.so'
removed 'libsum.so'
=> cleaned up!
+ echo '=> Compiling now...'
=> Compiling now...
+ CPPFLAGS='-std=c++14 -fPIC -I /home/sehe/custom/boost-di/include/'
+ LDFLAGS=
+ g++ -std=c++14 -fPIC -I /home/sehe/custom/boost-di/include/ sum.cpp -shared -o libsum.so
+ g++ -std=c++14 -fPIC -I /home/sehe/custom/boost-di/include/ dot_product.cpp -shared -o libdot_product.so
+ LDFLAGS=' -lboost_filesystem -lboost_system -ldl'
+ g++ -std=c++14 -fPIC -I /home/sehe/custom/boost-di/include/ application_main.cpp -o application_main -lboost_filesystem -lboost_system -ldl
+ g++ -std=c++14 -fPIC -I /home/sehe/custom/boost-di/include/ application_di.cpp -o application_di -lboost_filesystem -lboost_system -ldl
+ ./application_main .
[sum_constructor]
[dot_product_constructor]
[sum_constructor]
[sum_constructor]
[dot_product_constructor]

Plugin Name: sum
calculate(1, 2): 3

Plugin Name: dot_product
calculate(1, 2): 5
[~dot_product_destructor]
[~sum_destructor]
[~sum_destructor]
[~dot_product_destructor]
[~sum_destructor]
+ ./application_di . use_sum
[sum_constructor]
name: sum
[~sum_destructor]
+ ./application_di .
[sum_constructor]
[dot_product_constructor]
name: dot_product
[~dot_product_destructor]
[~sum_destructor]

或更多live: “在此处输入图像描述”

Shared pointer is the problem. The bind<> template argument cannot be a pointer or reference type

There's some information about why pointers are disallowed in bind<>: https://github.com/boost-ext/di/issues/317

I figured out a working way to bind the dependency:

const auto injector =
    di::make_injector(di::bind<ioperation>().to(
        [=, &use_sum](const auto& injector) -> op_ptr
        {
            return use_sum
                ? sum_creator()
                : dot_product_creator(sum_creator());
        }) //
    );

Note that capturing the factory functions by value keeps the DLL around as long as the injector exists. This is safer than capturing by reference.
Capturing the use_sum by reference highlights that the injector is dynamic. If that's not required, then I'd replace the whole injector with:

const auto injector = di::make_injector(di::bind<ioperation>().to(
    use_sum ? sum_creator() : dot_product_creator(sum_creator())) //
);

Full Demo

See also Github: https://github.com/sehe/boost-plugins-prework

  • File ioperation.hpp

     #pragma once
     #include <boost/shared_ptr.hpp>
     #include <string>
    
     struct ioperation {
       virtual std::string name() const                = 0;
       virtual float       calculate(float x, float y) = 0;
    
       virtual ~ioperation() = default;
     };
    
     using op_ptr = boost::shared_ptr<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 op_ptr create_sum() { return op_ptr(new sum()); }
         };
     } // namespace sum_namespace
    
     BOOST_DLL_ALIAS(
         sum_namespace::sum::create_sum, // <-- this function is exported with...
         create_sum                      // <-- ...this alias name
     )
    
  • File sum.hpp

     #pragma once
     #include "ioperation.hpp"
     #include "ioperation.hpp"
    
     namespace sum_namespace {
         struct sum : ioperation {
             sum();
             ~sum() override;
             std::string name() const override;
             float       calculate(float, float) override;
    
             static op_ptr create_sum();
         };
     } // namespace sum_namespace
    
  • File dot_product.cpp

     #include "dot_product.h"
     #include <boost/config.hpp>
     #include <boost/dll/alias.hpp>
     #include <boost/dll/import.hpp>
     #include <iostream>
    
     namespace dot_product_namespace {
    
         dot_product::dot_product(op_ptr& arg) {
             sum_ptr = arg;
             std::cout << "[dot_product_constructor]" << std::endl;
         }
    
         std::string dot_product::name() const { return "dot_product"; }
    
         float dot_product::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*/ op_ptr dot_product::create_dot_product(op_ptr sum_ptr) {
             return op_ptr(new dot_product(sum_ptr));
         }
    
         dot_product::~dot_product() {
             std::cout << "[~dot_product_destructor]" << std::endl;
         }
     }; // namespace dot_product_namespace
    
     BOOST_DLL_ALIAS(dot_product_namespace::dot_product::
                         create_dot_product, // <-- this function is exported with...
                     create_dot_product      // <-- ...this alias name
     )
    
  • File dot_product.h

     #pragma once
     #include "ioperation.hpp"
    
     namespace dot_product_namespace {
    
         struct dot_product : ioperation {
             dot_product(op_ptr&);
             ~dot_product() override;
             std::string name() const override;
             float       calculate(float, float) override;
    
             static op_ptr create_dot_product(op_ptr sum_ptr);
    
           private:
             op_ptr sum_ptr;
         };
     }; // namespace dot_product_namespace
    
  • File application_di.cpp

     #include "boost/function.hpp"
     #include "ioperation.hpp"
     #include <boost/di.hpp>
     #include <boost/dll/import.hpp>
     #include <iostream>
    
     namespace di = boost::di;
     namespace dll = boost::dll;
    
     class app {
      private:
        op_ptr ptr_;
    
      public:
          app(boost::shared_ptr<ioperation> ptr)
              : ptr_(ptr)
          {
              std::cout << "name: " << ptr_->name() << std::endl;
          }
     };
    
     using boost::filesystem::path;
    
     int main(int argc, char** argv) {
         // setting up paths to library(.so) files
         path lib_path(argc > 1 ? argv[1] : "."),
             child_library_path = lib_path / "dot_product",
             parent_library_path = lib_path / "sum";
    
         // defining function types for lib constructors
         using sum_create_t = op_ptr();
         using dot_product_create_t = op_ptr(op_ptr);
    
         // importing SUM lib factory
         auto sum_creator = boost::dll::import_alias<sum_create_t>(
             parent_library_path,
             "create_sum",
             dll::load_mode::append_decorations);
    
         // importing DOT_PRODUCT lib factory
         auto dot_product_creator =
             boost::dll::import_alias<dot_product_create_t>(
                 child_library_path,
                 "create_dot_product",
                 dll::load_mode::append_decorations);
    
         auto use_sum = true;
    
         const auto injector =
             di::make_injector(di::bind<ioperation>().to(
                 [=, &use_sum](const auto& injector) -> op_ptr
                 {
                     return use_sum
                         ? sum_creator()
                         : dot_product_creator(sum_creator());
                 }) //
             );
    
         use_sum = argc > 2;
         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;
     using boost::filesystem::path;
    
     int main(int argc, char** argv)
     {
         // setting up paths to library(.so) files
         path lib_path(argc > 1 ? argv[1] : "."),
             child_library_path = lib_path / "dot_product",
             parent_library_path = lib_path / "sum";
    
         // defining function types for lib constructors
         using sum_create_t = op_ptr();
         using dot_product_create_t = op_ptr(op_ptr);
    
         // importing SUM lib factory
         auto sum_creator = dll::import_alias<sum_create_t>(
             parent_library_path,
             "create_sum",
             dll::load_mode::append_decorations);
    
         // importing DOT_PRODUCT lib factory
         auto dot_product_creator =
             dll::import_alias<dot_product_create_t>(
                 child_library_path,
                 "create_dot_product",
                 dll::load_mode::append_decorations);
    
         auto sum_ptr = sum_creator();
         auto dot_product_ptr = dot_product_creator(sum_ptr);
    
         //executing calculate methods for object ptrs
         for (op_ptr op : {sum_creator(), dot_product_creator(sum_creator()) }) {
             std::cout << "\nPlugin Name: " << op->name() << "\n";
             std::cout << "calculate(1, 2): " << op->calculate(1, 2) << "\n";
         }
     }
    
  • File compile_n_run.sh

     #!/bin/bash
    
     set -e -x -u
     ./cleanup.sh
    
     echo "=> Compiling now..."
     CPPFLAGS="-std=c++14 -fPIC -I /home/sehe/custom/boost-di/include/"
     LDFLAGS=""
    
     # Required to compile on sehe's machine:
     #CPPFLAGS="$CPPFLAGS -I /home/sehe/custom/boost-di/include/"
     #CPPFLAGS="$CPPFLAGS -isystem /home/sehe/custom/superboost/ ";
     #LDFLAGS="$LDFLAGS -L /home/sehe/custom/superboost/stage/lib"
    
     g++ $CPPFLAGS sum.cpp -shared -o libsum.so $LDFLAGS
     g++ $CPPFLAGS dot_product.cpp -shared -o libdot_product.so $LDFLAGS
    
     # add application libraries
     LDFLAGS="$LDFLAGS -lboost_filesystem -lboost_system -ldl"
     g++ $CPPFLAGS application_main.cpp -o application_main $LDFLAGS
     g++ $CPPFLAGS application_di.cpp -o application_di $LDFLAGS
    
     ./application_main .
    
     ./application_di . use_sum
     ./application_di . # uses dot_product
    

Output

Using compile_n_run.sh:

+ ./cleanup.sh
removed 'application_main'
removed 'libdot_product.so'
removed 'libsum.so'
=> cleaned up!
+ echo '=> Compiling now...'
=> Compiling now...
+ CPPFLAGS='-std=c++14 -fPIC -I /home/sehe/custom/boost-di/include/'
+ LDFLAGS=
+ g++ -std=c++14 -fPIC -I /home/sehe/custom/boost-di/include/ sum.cpp -shared -o libsum.so
+ g++ -std=c++14 -fPIC -I /home/sehe/custom/boost-di/include/ dot_product.cpp -shared -o libdot_product.so
+ LDFLAGS=' -lboost_filesystem -lboost_system -ldl'
+ g++ -std=c++14 -fPIC -I /home/sehe/custom/boost-di/include/ application_main.cpp -o application_main -lboost_filesystem -lboost_system -ldl
+ g++ -std=c++14 -fPIC -I /home/sehe/custom/boost-di/include/ application_di.cpp -o application_di -lboost_filesystem -lboost_system -ldl
+ ./application_main .
[sum_constructor]
[dot_product_constructor]
[sum_constructor]
[sum_constructor]
[dot_product_constructor]

Plugin Name: sum
calculate(1, 2): 3

Plugin Name: dot_product
calculate(1, 2): 5
[~dot_product_destructor]
[~sum_destructor]
[~sum_destructor]
[~dot_product_destructor]
[~sum_destructor]
+ ./application_di . use_sum
[sum_constructor]
name: sum
[~sum_destructor]
+ ./application_di .
[sum_constructor]
[dot_product_constructor]
name: dot_product
[~dot_product_destructor]
[~sum_destructor]

Or more live:enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文