C++实现简单的类型库

很久以前看到有人问“如何在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。

不过我还有些怀疑这东西是否真的有用?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值