Qt动态库调用宿主进程中的对象方法纯虚函数使用

Qt动态库调用宿主进程中的对象方法纯虚函数使用

目录

引言

在运行时加载动态库并获取对象指针(QLibrary)

本贴重点:在动态库中调用宿主进程的对象方法

还是以add方法为例写一个Demo

引言

可执行程序加载动态库并调用动态库导出的函数是比较容易的:

导入库对应的头文件

在CPP文件中调用函数

在链接程序时加上动态库作为参数

假设demo.cpp中需要用到动态库libadd.so中的某个函数,可能是int add(int x, int y),那么我们编译时就需要链接上libadd.so, gcc参数中-L./libs指定了当前目录下的libs目录为库的目录,-ladd指定了libadd.so动态库文件,注意这里并未使用全称,让编译器自动适配即可。

// 该方式为静态导入方式(在程序未运行时完成导入) gcc demo.cpp -o demo -L./libs -ladd 在运行时加载动态库并获取对象指针(QLibrary) // 导入动态库 QLibrary m_library; m_library.setFileName("./libs/libadd.so"); assert(m_library.load()); // 获取函数指针 typedef int (*FUNC_ADD)(int, int); FUNC_ADD add = (FUNC_ADD)m_library.resolve("add"); assert(add); // 愉快的使用add函数 int a = add(125, 125); qDebug() << a; 本贴重点:在动态库中调用宿主进程的对象方法

先复习下两个概念:纯虚函数虚函数表

纯虚函数在类中定义后是可以不用实现的,子类如继承含有纯虚函数的类必须实现该类所有的纯虚函数。纯虚函数可作接口使用。

C++拥有虚函数表(V-Table),存储着虚函数地址的表。

假设动态库需要调用宿主进程的对象方法,在动态库编译时时无法获取到宿主程序该对象的实现的,所以按照正常逻辑是无法编译通过的。

但是通过上边有效的复习可以知道纯虚函数在调用时可无需实现(在运行时通过查询虚函数表后获取实际地址),这样就可以顺利的完成了编译,当动态库被加载进宿主进程后就可以正常调用对象的方法了。

还是以add方法为例写一个Demo

宿主程序:

#ifndef __MATH_H__ #define __MATH_H__ // 接口定义 class IMath { public: virtual int add(int x, int y) = 0; }; typedef void (*FUNC_SET_OBJ)(void*); class Math: public IMath { public: Test() { m_library.setFileName("./libs/libtest.so"); assert(m_library.load()); FUNC_SET_OBJ setObj= (FUNC_SET_OBJ)m_library.resolve("setObj"); assert(setObj); // 将Math实例传递给动态库 setObj(this); } int add(int x, int y) ovdrride { return x + y; } private: QLibrary m_library; } #endif

然后将接口做成一个独立的头文件imath.h,用来给动态库调用

#ifndef __IMATH_H__ #define __IMATH_H__ class IMath { public: virtual int add(int x, int y) = 0; }; #endif

动态库程序(libtest.cpp):

void setObj(void* obj) { IMath* math = static_cast<IMath*>(obj); qDebug() << math->add(125, 125); }

将动态库程序编译后放入libs目录下给宿主程序调用,在宿主程序中实例化Math类,并调用其Test方法,在Test方法中会加载动态库,并将Math实例的指针传递给动态库,动态库将Math实例强转为接口类型并调用其中的纯虚函数add()

以上就是Qt动态库调用宿主进程中的对象方法纯虚函数使用的详细内容,更多关于Qt动态库调用宿主进程纯虚函数的资料请关注易知道(ezd.cc)其它相关文章!

推荐阅读