很久以前看到有人问“如何在C++中实现动态加载类”时,简单地做了一个。
不过当时没有去考虑动态加载DLL的情况。
今天在 cpp@codingnow.com中也有人问到这个问题,就把它给做完了。
当然只是简单地做到了“从全局类型库中,根据类名创建实例,支持动态DLL加载”,说得更明白点:
在应用程序App1中,向全局类型库中注册一个类型"Test",在另一个隐式链接的DLL中(即App1一启动就加载的DLL),向全局类型库中注册另外几个类型。这时可以在App1中通过类型的名字生成实例。
在另一个显式加载的DLL中(即调用LoadLibrary加载),向全局类型库中注册其它几个类型。这时通过LoadLibrary加载这个DLL,就可以生成这几个类型的实例了。
这地方不能上传文件,就把代码贴一点吧:
typelib.h文件:
typelib.cpp文件:
把它编译成静态lib或DLL,就可以使用了。
在那2个为我们提供类型的DLL中,DllMain函数中加入下面的代码:
就可以向全局类型库中注册类型。注意在类型库中是没有保存类信息的,所以最好是使用单根类库来做。
下面是一点测试代码:
还有一个没考虑的地方,就是没有给它加锁,因为有可能在一个线程中加载一个DLL。
不过我还有些怀疑这东西是否真的有用?
不过当时没有去考虑动态加载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__
#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);
}
#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 > );
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 ;
}
{
// 程序启动时注册类型。
// 实际上启动时就加载了另一个动态链接库,那里面有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。
不过我还有些怀疑这东西是否真的有用?