很久以前看到有人问“如何在C++中实现动态加载类”时,简单地做了一个。
不过当时没有去考虑动态加载DLL的情况。
今天在
cpp@codingnow.com中也有人问到这个问题,就把它给做完了。
当然只是简单地做到了“从全局类型库中,根据类名创建实例,支持动态DLL加载”,说得更明白点:
在应用程序App1中,向全局类型库中注册一个类型"Test",在另一个隐式链接的DLL中(即App1一启动就加载的DLL),向全局类型库中注册另外几个类型。这时可以在App1中通过类型的名字生成实例。
在另一个显式加载的DLL中(即调用LoadLibrary加载),向全局类型库中注册其它几个类型。这时通过LoadLibrary加载这个DLL,就可以生成这几个类型的实例了。
这地方不能上传文件,就把代码贴一点吧:
typelib.h文件:
#ifndef __TYPE_LIB_H__
#define __TYPE_LIB_H__
typedef void*(*CREATE_FUNC)();
typedef void(*RELEASE_FUNC)(void*);
void regtype (const char* name, CREATE_FUNC cfunc, RELEASE_FUNC rfunc);
void* createObject (const char* name);
void releaseObject (const char* name, void* p);
struct ITestInterface
{
virtual ~ITestInterface () {}
virtual void print () const = 0;
};
template <class T>
void* create ()
{
return new T;
}
template <class T>
void release (void* p)
{
delete (T*)p;
}
#endif // __TYPE_LIB_H__
typelib.cpp文件:
#include "typelib.h"
#include <string>
#include <map>
using namespace std;
namespace TypeRegistry
{
static map < string, pair<CREATE_FUNC, RELEASE_FUNC> > types_info;
template <class T>
void regType (const string& name)
{
types_info.insert (make_pair(name, make_pair(create<T>, release<T>)));
}
}
void regtype (const char* name, CREATE_FUNC cfunc, RELEASE_FUNC rfunc)
{
TypeRegistry::types_info.insert (make_pair(name, make_pair(cfunc, rfunc)));
}
void* createObject (const char* name)
{
map < string, pair<CREATE_FUNC, RELEASE_FUNC> >::const_iterator iter;
iter = TypeRegistry::types_info.find (name);
if (iter != TypeRegistry::types_info.end ())
return (*iter->second.first)();
return NULL;
}
void releaseObject (const char* name, void* p)
{
map < string, pair<CREATE_FUNC, RELEASE_FUNC> >::const_iterator iter;
iter = TypeRegistry::types_info.find (name);
if (iter != TypeRegistry::types_info.end ())
(*iter->second.second)(p);
}
把它编译成静态lib或DLL,就可以使用了。
在那2个为我们提供类型的DLL中,DllMain函数中加入下面的代码:
// FirstTest和SecondTest是2个类名
regtype("FirstTest", create<FirstTest>, release<FirstTest>);
regtype("FirstTest", create<SecondTest>, release<SecondTest>);
就可以向全局类型库中注册类型。注意在类型库中是没有保存类信息的,所以最好是使用单根类库来做。
下面是一点测试代码:
int main()
{
// 程序启动时注册类型。
// 实际上启动时就加载了另一个动态链接库,那里面有3个类型,所以现在有4个类型
regtype ("MyTest", create<MyTest>, release<MyTest>);
while (1)
{
string class_name;
cin >> class_name;
if (class_name == "q")
break;
// 当输入load时,把另一个动态链接库加载进来,那个链接库中有2个类型,现在共有6个类型可用。
if (class_name == "load")
{
LoadLibrary("typelibdll_test.dll");
continue;
}
ITestInterface* test = (ITestInterface*)createObject (class_name.c_str());
if (!test)
{
cout << "This type not found" << endl;
continue;
}
test->print ();
releaseObject (class_name.c_str(), test);
}
return 0;
}
还有一个没考虑的地方,就是没有给它加锁,因为有可能在一个线程中加载一个DLL。
不过我还有些怀疑这东西是否真的有用?
相关推荐
文中是linux下 C++动态库 实现接口提供类导出的一个例子 注意其中使用函数返回基类指针的用法,因为Linux的动态链接库不能像MFC中那样直接导出类 一、介绍 如何使用dlopen API动态地加载C++函数和类,是Unix C++...
C++ 标准库头文件 具名要求 功能特性测试 (C++20) 工具库 类型支持(基本类型、RTTI、类型特性) 概念库 (C++20) 错误处理 动态内存管理 日期和时间工具 字符串库 容器库 迭代器库 范围库 (C++20) 算法库 数值库 ...
纯C++标准库实现,仅用到了<fstream><map><list><string>,这些标准库,没有在Linux下测试过。(简易实现,代码部分仅6K,全采用string类型) /* .ini 文件 解析器【只能读取】 Section和Key只能为字母、数字、...
Implementation of Template-based, type-safe and generic Observer Pattern for C++基于模板、类型安全、通用的观察者模式的C++实现;包含库文件和使用示例。
C++调用C#实现Xml读写,简单来说就是C++利用C#对Xml的Dom文档对象操作方式来实现xml的读写,涉及C++调用C#的Dll动态库,C++与C#的部分类型转换。详见空间博客。
本算法可以在Microsoft Visual Studio并且安装了EasyX图形库的前提下实现功能。 同时要学习C++图形库相关的知识,也可以点击我的主页,找到EasyX专栏进行图形库的学习。 值得注意的是,在使用本算法时需要调用...
统计你的工程的代码行数,可以设置过滤的文件类型,支持批量添加文件,用Visual C++开发。 该工具用来统计你的工程的代码行数。可设置是否计算空行,可配置过滤的文件类型。 支持以目录添加或以文件添加,如果以...
类型支持 − 特性 (C++11) 程序工具 关系运算符 (C++20) numeric_limits − type_info initializer_list (C++11) 概念库 (C++20) 诊断库 通用工具库 智能指针与分配器 日期和时间 函数对象 − hash (C++11) ...
数据结构》抽象数据类型模板库及常用算法的面向对象C++实现毕业论文.docx
各微X之间只要有一个服务登录,则其它服务简单确认后视为自动登录。 6、功能展示要求(main函数) (1)设计约定。开通服务情况、群成员信息和好友信息可以预先保存到文件中,在系统启动时将这些信息加载到内存中;...
大致限于泛型编程,但一些系统级的代码,尤其是对通用性、性能要求极高的基础库(如 STL、Boost)几乎不可避免的都大量地使用 C++ 模板,一个稍有规模的大量使用模板的程序,不可避免的要涉及元编程(如类型计算)。...
使用c++实现boost::any类 any类可以存放任意类型数据,如: void test_any() { any any_a1(123); int a2 = any_cast(any_a1); int* p_a2 = any_cast(&any_a1); std::cout *p_a2="*p_a2; any any_b1(12.35); ...
语义分析主要完成两个任务,其一是构建符号表,二是进行类型检查。 首先,需要把语法分析生成的语法树读入,然后真的搭建成一棵树型结构。 然后,对树形结构上的每一个节点进行递归遍历,在此过程中进行类型检查与...
详细演示了如何通过JNA实现以下形式的动态链接库接口: 1:基本数据类型 2:基本数据类型的指针和引用 3:结构体 4:结构体的指针和引用 5:函数指针和回调函数 6:字符串指针 7:输入一个数组 8:输出一个数组并...
管理系统是一种通过计算机技术实现的用于组织、监控和控制各种活动的软件系统。这些系统通常被设计用来提高效率、减少错误、加强安全性,同时提供数据和信息支持。以下是一些常见类型的管理系统: 学校管理系统: ...
dtl, 由 C++ 编写的diff模板库 dtl dtl 是用 C++ 编写的diff模板库。 模板的NAME 是 C++的模板。目录特性正在开始运行。比较两个字符串。比较两个数据具有任意类型。合并三个序列。补丁函数差异作为统一格式比较大...
提供了大量面向对象设计转换成C++实现的准则。 .展示了如何用模板支持可重用性。 .描述了重要的大型系统开发问题,包括库结构的设计、异常处理和分布式处理。 . 本书是C++系统程序员或应用程序员工作的必备手册。 ...
大多数在C++实现属性的库和编译器使用扩展技术,如Managed C++或C++ Builder,或者他们使用如通常函数的set和get方法,但那不是属性。 详述 我们首先看一下什么是属性。一个属性表现为一个字段或者成员变量,但它...
一共有四个类,不仅可以卖吉他,还有其他类的乐器可以出售,而且,要提供初始化库存信息,所以用了TXT文件输入输出,比较简单,还有可以根据不同的属性查询乐器,有:名称,价格,制造商,背板材料,模型,类型等,...