Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/164.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++;在linux平台上运行时加载共享库和提取类实现 在C++中,是否可以在执行时加载共享库?_C++_Linux_Qt_Qt4_Shared Libraries - Fatal编程技术网

C++;在linux平台上运行时加载共享库和提取类实现 在C++中,是否可以在执行时加载共享库?

C++;在linux平台上运行时加载共享库和提取类实现 在C++中,是否可以在执行时加载共享库?,c++,linux,qt,qt4,shared-libraries,C++,Linux,Qt,Qt4,Shared Libraries,我希望用户选择在运行时加载哪个共享库,而无需重新编译整个程序 dlopen()是C的解决方案,但我的程序是用C++/Qt编写的,要提取的符号是Qt样式的类,是否有更“C++”的方法来实现这一点。是的,可以在大多数操作系统上实现您所描述的功能,但是,你如何做到这一点取决于系统,无论是什么系统,你都需要付出更多的努力才能实现这一点 一般步骤如下: 加载库 对于库中您感兴趣的每个符号,找到它并将其存储到一个变量以供以后使用。(这可以根据需要进行,而不是立即进行。) 例如,在*nix类型系统上的伪代码(

我希望用户选择在运行时加载哪个共享库,而无需重新编译整个程序


dlopen()
是C的解决方案,但我的程序是用C++/Qt编写的,要提取的符号是Qt样式的类,是否有更“C++”的方法来实现这一点。

是的,可以在大多数操作系统上实现您所描述的功能,但是,你如何做到这一点取决于系统,无论是什么系统,你都需要付出更多的努力才能实现这一点

一般步骤如下:

  • 加载库
  • 对于库中您感兴趣的每个符号,找到它并将其存储到一个变量以供以后使用。(这可以根据需要进行,而不是立即进行。)
  • 例如,在*nix类型系统上的伪代码(读:这不会编译!)中,假设您的共享库中包含以下内容:

    // I'm declaring this _extern "C"_ to avoid name mangling, making it easier to
    // specify a symbol name for dlsym() later
    extern "C" int myFunction() {
        return 10;
    }
    
    假设它位于一个名为libmyFunction.so的库中。例如,您的主应用程序可以:

    {
        void *handle = dlopen("libmyFunction.so", <flags>);
        if (!handle) return; // error: cannot locate the library!
    
        int (*func)() = (int (*)())dlsym(handle, "myFunction");
        if (!func) return; // error: cannot locate the symbol!
    
        printf("The function returns: %d\n", func());
    }
    
    {
    void*handle=dlopen(“libmyFunction.so”,);
    if(!handle)return;//错误:找不到库!
    int(*func)(=(int(*)dlsym(句柄,“myFunction”);
    if(!func)return;//错误:找不到符号!
    printf(“函数返回:%d\n”,func());
    }
    

    如果需要在Windows上执行此操作,则概念相同,但函数调用不同。

    您可以在Qt中使用
    QLibrary
    以两种方式执行此操作。以下示例在运行时以两种不同的方式从共享库调用函数:

    #include <QLibrary>
    #include <QDebug>
    
    class  Dynamic_library
    {
    public:
        Dynamic_library();
        virtual int sum( int len, int * data );
    };
    
    typedef Dynamic_library * (*get_object_func)();
    typedef int (*call_sum_func)(int len , int * data);
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
    
        QLibrary library( "./dynamic_library" );
        library.load();
        if( !library.isLoaded() )
        {
            qDebug() << "Cannot load library.";
            return 0;
        }
        call_sum_func call_sum = (call_sum_func)library.resolve( "call_sum" );
        if( call_sum )
        {
            //Dynamic_library * obj=get_object();
    
            int * a=new int[3];
            a[0]=2;
            a[1]=3;
            a[2]=4;
            qDebug() << "sum of 2+3+4' = " << call_sum( 3, a ) <<"\n";
    
            delete [] a;
        }
    
        get_object_func get_object = (get_object_func)library.resolve( "get_object" );
        if( get_object )
        {
            Dynamic_library * obj=get_object();
    
            int * a=new int[3];
            a[0]=7;
            a[1]=8;
            a[2]=9;
            qDebug() << "sum of 7+8+9' = " << obj->sum(3, a );
    
            delete [] a;
        }
    
        return a.exec();
    }
    
    #包括
    #包括
    类动态库
    {
    公众:
    动态_库();
    虚拟整数和(整数长度,整数*数据);
    };
    typedef动态_库*(*get_object_func)();
    typedef int(*调用函数)(int len,int*数据);
    int main(int argc,char*argv[])
    {
    qcorea应用程序(argc、argv);
    QLibrary library(“动态库”);
    load();
    如果(!library.isLoaded())
    {
    
    qDebug()如果目标库本身或至少其规范在您的控制下,那么您不应该使用
    QLibrary
    -而是使用。它不需要通过指针调用,否则需要

    <>如果你坚持使用<代码> DLOPEN//C>类似的机制,关于<代码> QLibrary < /C> >没有什么C特定的。明显的限制是,你要打开的库必须是用C++编译器编译的,它与你用来编译自己代码的AB兼容。C版本

    除此之外,您还必须这样做。完成后,您可以使用与符号匹配的函数/方法指针调用符号。这是通过设计实现的。如果您希望创建对象的新实例,则需要库提供的静态工厂方法

    如果库不提供工厂方法,则可以实现一个垫片库,该垫片库通过泛型名称链接到目标库,并提供工厂方法。您仍然需要通过函数/方法指针调用各个方法

  • 创建一个临时文件夹
  • 将垫片库复制到临时文件夹
  • 将重命名为通用名称的目标库复制到临时文件夹中
  • 保存
    LD\u LIBRARY\u PATH
    环境变量的值
  • 将临时文件夹前置到
    LD\u LIBRARY\u PATH
  • 打开/加载库
  • 还原
    LD\u LIBRARY\u PATH的保存值

  • 当然,对于库公开的任何接口,都必须有头文件。通常情况下,只要有一个动态库文件,就无法重建头文件-主要是因为损坏的符号没有所用类型的完整结构信息。例如,即使可以找到给定类的构造函数,也不知道有多大是类实例(其
    sizeof
    ).

    这是什么平台?是的,这是可能的,但与运行时如何将共享库加载到程序中的操作系统无关。从代码中运行共享库有什么特殊问题?我想从库中提取的是qt类,我不知道在qt中,有一种机制可以做到这一点,或者没有。我已经把共享库的代码添加到答案中。正如你所看到的,外部“C”给了你一个访问C++类动态的可能性。必须吗?必须是虚拟的。因为我们在使用它时声明它,而不定义它。非常感谢,我还发现我无法从类中检索静态成员
    class DYNAMIC_LIBRARYSHARED_EXPORT Dynamic_library
    {
    public:
        Dynamic_library();
        virtual int sum( int len, int * data );
    };
    
    extern "C" Q_DECL_EXPORT Dynamic_library * get_object()
    {
         return new Dynamic_library();
    }
    
    extern "C" Q_DECL_EXPORT int call_sum(int len, int * data)
    {
         return Dynamic_library().sum(len,data);
    }
    
    
    Dynamic_library::Dynamic_library()
    {
    
    }
    
    int Dynamic_library::sum( int len, int *data )
    {
        int sum = 0;
        for(int i=0; i<len; ++i )
            sum += data[i];
    
        return sum;
    }