现在的位置: 首页 > 综合 > 正文

第一个com程序_不使用微软的东西。

2013年09月21日 ⁄ 综合 ⁄ 共 4959字 ⁄ 字号 评论关闭

一句话:如果你真正理解dll那么实现com实在是太容易了。在我的blog里有我写的关于dll的系列文章。

当然我在这里说多是c++的实现。因为com就是利用了dll的动态连接的特性,加上面相对象的封装,同时由于dll为了实现动态链接 所以它不能不有些限制,正是由于这些限制导致了 特殊化的写com的方式。或者说倒至了特殊化的封装方式。

//一下是dll部分

//..............................interface.h...........................

//#define struct interface
//类 或者接口的标识符号
#define INO    10
#define IANO   11
#define IBNO   12
//................
#define CANO            20
//...................

class I
{
public:
 virtual int AddRef()=0;
 virtual bool Release()=0;
 virtual bool QueryInterface (int I_ID, void **pOutInterface)=0;
};

class IA
{
public:
 virtual void fna1(int i)=0;
 virtual void fna2(int i)=0;
};

class IB
{
public:
 virtual void fnb1(int i)=0;
 virtual void fnb2(int i)=0;
};
 

//...................................................................

//................a.h................................

#pragma warning(disable: 4786)

#if !defined(AFX_A_H__BB099D15_A5F3_4E71_8760_1D2F67814BC4__INCLUDED_)
#define AFX_A_H__BB099D15_A5F3_4E71_8760_1D2F67814BC4__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
//..............................
#include "interface.h"
//#include "IUnknown.h"
#include <map>
#include <string>
using namespace std;
//................

class CA  :public IA,public IB, public I
{
public:
 CA();
 virtual ~CA();
 virtual int AddRef();
 virtual bool Release();
 virtual bool QueryInterface( int I_ID, void **pOutInterface);
 virtual void fna1( int i );
 virtual void fna2(int i );
 virtual void fnb1( int i );
 virtual void fnb2(int i );
protected:
 int m_iRef;
 map<int , void*> m_map_iidtoi;
public:
 typedef map<int , void*>::value_type VTMAPIIDTOI;
 typedef map<int , void*>::iterator  ITMAPIIDTOI;
};

extern "C"
{
 __declspec(dllexport)  /*bool*/void  CreateInstance(int CLS_ID, int I_ID, //in
  void **ppi);//out
};

//只有一个用来生成类对象的导出函数
#endif // !defined(AFX_A_H__BB099D15_A5F3_4E71_8760_1D2F67814BC4__INCLUDED_)

//......................................................................

//......................................................

// A.cpp: implementation of the CA class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "A.h"
#include <iostream>
using namespace std;

// TryCom3.cpp : Defines the entry point for the DLL application.

BOOL APIENTRY DllMain( HANDLE hModule,
       DWORD  ul_reason_for_call,
       LPVOID lpReserved
       )
{
    switch (ul_reason_for_call)
 {
 case DLL_PROCESS_ATTACH:
 case DLL_THREAD_ATTACH:
 case DLL_THREAD_DETACH:
 case DLL_PROCESS_DETACH:
  break;
    }
    return TRUE;
}

// This is the constructor of a class that has been exported.
// see TryCom3.h for the class definition
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CA::CA()
{
 //this->m_iRef =1;
 this->m_map_iidtoi.insert( VTMAPIIDTOI(INO, static_cast<void*>( static_cast<I*>(this) ) ) );
 this->m_map_iidtoi.insert( VTMAPIIDTOI(IANO,static_cast<IA*>(this)) );//×Ô¶¯»áת»»
 this->m_map_iidtoi.insert( VTMAPIIDTOI(IBNO,static_cast<IB*>(this)) );
}

CA::~CA()
{

}
int CA::AddRef()
{
 ++m_iRef;
 return m_iRef;
}

bool CA::Release()
{
 m_iRef -- ;
 if ( m_iRef == 0)
 {
  delete this;
 }
 return true;
}

bool CA::QueryInterface(int I_ID, void **pOutInterface)
{
 CA::ITMAPIIDTOI it=this->m_map_iidtoi.find(I_ID);
 if( it== this->m_map_iidtoi.end() )
 {
  *pOutInterface=NULL;
  return false;
 }
 *pOutInterface = (*it).second ;
 return true;
}
void CA::fna1( int i )
{
 cout<<"CA::IA::fna1  verison =2 "<<"input para: "<<i<<endl;
 
}
void CA::fna2(int i )
{
 cout<<"CA::IA::fna2  verison =2 "<<"input para: "<<i<<endl;
}
void CA::fnb1( int i )
{
 cout<<"CA::IA::fnb1  verison =2 "<<"input para: "<<i<<endl;
}
void CA::fnb2(int i )
{
 cout<<"CA::IA::fnb2  verison =2 "<<"input para: "<<i<<endl;
}

//////////////////////////
//bool
void  CreateInstance(int CLS_ID, int I_ID, //in
  void **ppi)//out
{
 if ( CLS_ID == CANO )
 {
  CA *p= new CA;
  p->QueryInterface( I_ID , ppi );
  if ( *ppi == NULL )
  {
   return ;//false;
  }
  return ;//true;/* */
 }
 else
 {
  *ppi = NULL;
  return;// true;
 }
}
//........................................................................

//一下是客户端部分

// UseTryCom3.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "windows.h"
#include "../interface.h"
#include <iostream>
#include <string>
using namespace  std ;

int main(int argc, char* argv[])
{
 HMODULE hm= ::LoadLibrary("E://lianxi//DLL_LIB_DCOM_COM//TryCom3//Debug//TryCom3.dll");
 if (hm == NULL)
 {
  cout<<"LoadLibrary error"<<endl;
  return 0;
 }
 typedef /*bool*/ void  (*pfnCreateInstance)(int , int , void **);
 pfnCreateInstance pfnci=(pfnCreateInstance)::GetProcAddress(hm,"CreateInstance");
 if (pfnci==NULL)
 {
  cout<<"get CreateInstance address error/n";
  return 0;
 }
 I *pi=NULL;
 pfnci(CANO, INO ,(void **)&pi);
 if (pi==NULL)
 {
  cout<<"get pi error/n";
  return 0;
 }
 pi->AddRef();
 IA *pia= NULL;
 pi->QueryInterface( IANO , (void **)&pia );
 if (pia==NULL)
 {
  cout<<"get pia error/n";
  return 0;
 }
 pi->AddRef();
 pia->fna1(10);
 pia->fna2(11);
 
 IB *pib= NULL;
 pi->QueryInterface( IBNO , (void **)&pib );
 if (pib==NULL)
 {
  cout<<"get pib error/n";
  return 0;
 }
 pi->AddRef();
 pib->fnb1(20);
 pib->fnb2(21);

 pi->Release();
 pi->Release();
 return 0;
}

//..................................

现在发觉很多介绍com的书都没有很好的介绍显式使用dll的方法。或者说显式使用dll导出类的方法。事实上正是由于dll的特性导致了com必须这么写。或者说com之所以这样是由于dll的特性(或者说是 局限性)加上封装。

【上篇】
【下篇】

抱歉!评论已关闭.