c++到com组件过度(一个实例)

com的核心体系结构来源于c++标准实现


c++的重用机制有一个严重的缺陷:要想试用该源对象就必须提供源代码,这样的话宝贵的技术会随之暴露。要解决这个问题在windows下可以使用DLL(dynamic link library 动态链接库),即将数据库对象的所有代码都打包成一个DLL,并提供一个或多个用于说明函数和结构的头文件。

动态链接库的使用原理:编译链接可执行文件时,只需要链接引入库DLL中的函数代码和数据并不复制到可执行文件中,在运行的时候,再去加载DLL访问DLL中导出的函数,这种方式称为动态链接。

首先学会创建动态库:(vc下创建)

1.在vc下新建一个动态库文件


2.选择动态库文件,工程名


3.选择第三个,它会自动生成统一的.cpp和.h文件


4.这样我们的动态库文件就建立完毕了


打开以后就是这个样子


将使用的函数声明继续往类中添加

函数实现放在.cpp中


如果在编译时出现这样的错误时:


请按照下方操作:



这是关于预处理的问题。。。。了解详情请问度娘^_^

动态库编译成功的标志:当当当




要将对象的实现封装成DLL,必须实现成员函数的引出,而引出成员函数最简单的方法是__declspec(dllexport)例如:

__declspec(dllexport)用于任何函数包括类的成员函数



应用程序要使用动态链接库可采用隐式和显式两种方法

隐式链接:

1.客户需将使用.dll .lib .h 文件添加到该工程文件夹下

2.在该工程的Project->Setting->Link->Object/library modules中加入xxxx.lib


显式链接过于复杂不在赘述

---------------------------------------------------------------------------------------------------------------

前面所创建的一个简单例子在这里说明一下:

  • 某库厂商开发一个算法,能在常时间内进行子串的查找工作。特点是其查找时间与目的串的长度无关。 该厂商创建了一个字符串类。为此,他生成了一个头文件和一个实现文件

// The following ifdef block is the standard way of creating macros which make exporting 
// from a DLL simpler. All files within this DLL are compiled with the FASTSTRING_EXPORTS
// symbol defined on the command line. this symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see 
// FASTSTRING_API functions as being imported from a DLL, wheras this DLL sees symbols
// defined with this macro as being exported.
#ifdef FASTSTRING_EXPORTS
#define FASTSTRING_API __declspec(dllexport)
#else
#define FASTSTRING_API __declspec(dllimport)
#endif

// This class is exported from the Faststring.dll
class FASTSTRING_API CFaststring {
	char * m_psz;
public:
	CFaststring(void);
	// TODO: add your methods here.
	CFaststring (const char*psz);
	~CFaststring ();
	int Length(void)const;
	char* Find(const char*psz)const;
};

extern FASTSTRING_API int nFaststring;

FASTSTRING_API int fnFaststring(void);

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

#include "stdafx.h"
#include "Faststring.h"
#include
    
    
     
     

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 an example of an exported variable
FASTSTRING_API int nFaststring=0;

// This is an example of an exported function.
FASTSTRING_API int fnFaststring(void)
{
	return 42;
}

// This is the constructor of a class that has been exported.
// see Faststring.h for the class definition
CFaststring::CFaststring()
{ 
	return; 
}
CFaststring::CFaststring(const char* psz):m_psz(new char[strlen(psz)+1])
{strcpy(m_psz,psz);}  //分配内存

CFaststring::~CFaststring(void)
{ delete []m_psz;}    //释放内存

int CFaststring::Length(void) const{
	return strlen(m_psz);}  //计算长度

char* CFaststring::Find(const char*psz)const
{
	return strstr(m_psz,psz);
} //查找子串


    
    

提到动态链接就不得不提静态链接:
  • 静态链接
    • 许多类库的做法
    • 编译时刻的链接
  • 静态链接的缺点
    • 代码重复:多个程序各有自己的代码,需要更多的内存
    • 客户程序占据更多的外存空间
    • 库代码更新需要重新编译所有的客户程序
  • 动态链接
    • 运行时刻的链接
  • 动态链接形式
    • 编译时刻通过引入库
    • 运行时刻完全动态


---------------------------------------------------------------------------------------------------------------


  • 改造FastString,令其Length()函数的复杂度为O(1)。 
  • 解决方法:需要添加一个私有成员来直接计数字符串长度


// The following ifdef block is the standard way of creating macros which make exporting 
// from a DLL simpler. All files within this DLL are compiled with the FASTSTRING2_EXPORTS
// symbol defined on the command line. this symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see 
// FASTSTRING2_API functions as being imported from a DLL, wheras this DLL sees symbols
// defined with this macro as being exported.
#ifdef FASTSTRING2_EXPORTS
#define FASTSTRING2_API __declspec(dllexport)
#else
#define FASTSTRING2_API __declspec(dllimport)
#endif

// This class is exported from the FastString2.dll
class FASTSTRING2_API CFastString2 {
public:
	CFastString2(void);
	// TODO: add your methods here.
	int m_cch;//v2.0 为了支持这个新的算法, 必须增加一个成员变量,以存储字符串的长度. 在构造函数中被赋值, 以后,当客户查询长度时,直接返回,无需计算. 导致了头文件的更新.
	char * m_psz;

	CFastString2 (const char*psz);
	~CFastString2 ();
	int Length(void)const;
	char* Find(const char*psz)const;

};

extern FASTSTRING2_API int nFastString2;

FASTSTRING2_API int fnFastString2(void);

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

#include "stdafx.h"
#include "FastString2.h"

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 an example of an exported variable
FASTSTRING2_API int nFastString2=0;

// This is an example of an exported function.
FASTSTRING2_API int fnFastString2(void)
{
	return 42;
}

// This is the constructor of a class that has been exported.
// see FastString2.h for the class definition
CFastString2::CFastString2()
{ 
	return; 
}

CFastString2::CFastString2(const char* psz)
:m_cch(strlen(psz)), m_psz(new char[m_cch+1])
{strcpy(m_psz,psz);}//长度保存下来

CFastString2::~CFastString2(void)
{ delete []m_psz;}

int CFastString2::Length(void) const{
	return m_cch;}// 直接返回, 无需计算, 提高了效率.

char* CFastString2::Find(const char*psz)const
{	return strstr(m_psz,psz);}// 查找子串



由于我们将类重新定义造成,新老客户使用DLL文件会不兼容配置混 问题的根源在于C++的编译模型,这种模型不能支持独立的二进制组件的设计。客户必须准确地知道对象的布局结构,从而导致客户和库的强的耦合关系。客户与库的紧密耦合性使得在不重新编译客户的情况下,无法实现类的替换。
明白的说就是:用户很开心升级了软件,刚开始还可以运行后来就弹出了一个对话框发生了异常,并且用户的所有工作都丢失了,当他试着再启动程序时,这个对话框又弹了出来。。。。。发生这个原因大概就是,上一个版本类定义给客户只分配了4个字节并传给了构造函数,升级以后的版本传给构造和析构的却是8个字节,并且要对这8个字节毫无保留的写入,不幸的是后4个字节属于别人,你这样非法操作,操作系统就把你终止掉喽(╥﹏╥)

---------------------------------------------------------------------------------------------------------------


解决方案:接口与实现分离
构造两个类一个接口类,一个实现类
  • 接口类只描述希望客户知道的底层数据面貌
  • 接口类不应包含任何用于对象实现的数据成员,应只包含操作方法的声明。
  • 实现类将包含具体的数据成员与操作方法的具体实现。
  • 接口类的二进制布局不会随着实现类数据成员的添加或删除而改变

// The following ifdef block is the standard way of creating macros which make exporting 
// from a DLL simpler. All files within this DLL are compiled with the FASTSTRINGITF_EXPORTS
// symbol defined on the command line. this symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see 
// FASTSTRINGITF_API functions as being imported from a DLL, wheras this DLL sees symbols
// defined with this macro as being exported.
#ifdef FASTSTRINGITF_EXPORTS
#define FASTSTRINGITF_API __declspec(dllexport)
#else
#define FASTSTRINGITF_API __declspec(dllimport)
#endif

// This class is exported from the FastStringItf.dll
class FastString;  // 声明实现类, 但是不需要包含实现类的头文件
class FASTSTRINGITF_API CFastStringItf {
public:
	CFastStringItf(void);
	// TODO: add your methods here.
	
	FastString* m_pThis;  //实现类的指针.

    CFastStringItf(const char*psz);
     ~CFastStringItf();
     int Length(void)const;
     char* Find(const char*psz) const;

};

extern FASTSTRINGITF_API int nFastStringItf;

FASTSTRINGITF_API int fnFastStringItf(void);

class FastString{
	char * m_psz;  //保存原始的字符串
	int m_cch;
public:
	FastString(const char*psz);   //构造函数
	~FastString(void);
	int Length(void)const;          //返回该字符串的长度
	char* Find(const char*psz)const;     //查找指定的子串
};
//
#include "FastString.h"
#include "string.h"

FastString::FastString(const char* psz):m_cch(strlen(psz)),m_psz(new char[m_cch+1])
{strcpy(m_psz,psz);}//长度保存下来

FastString::~FastString(void)
{ delete []m_psz;}

int FastString::Length(void) const{
	return m_cch;}// 直接返回, 无需计算, 提高了效率.

char* FastString::Find(const char*psz)const
{	return strstr(m_psz,psz);}// 查找子串

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

#include "stdafx.h"
#include "FastStringItf.h"
#include "FastString.h"

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 an example of an exported variable
FASTSTRINGITF_API int nFastStringItf=0;

// This is an example of an exported function.
FASTSTRINGITF_API int fnFastStringItf(void)
{
	return 42;
}

// This is the constructor of a class that has been exported.
// see FastStringItf.h for the class definition
CFastStringItf::CFastStringItf()
{ 
	return; 
}

CFastStringItf::CFastStringItf(const char *psz):m_pThis(new FastString(psz))//构造函数里面生成了实现类的具体事例通过这个指针指向实现类
{}
//{assert(m_pThis!=0);}//判断实现类是否为空

 CFastStringItf::~CFastStringItf(void){
         delete m_pThis;}//析构函数最后调用
   
int CFastStringItf::Length(void) const{
          return  m_pThis->Length();}//传递到实现类的lengh

char* CFastStringItf::Find(const char*psz)const{
          return m_pThis->Find(psz);}


其实这个改进的本意是:使上面出现的bug不再出现,用一个句丙类作为接口,并不暴露源码也就是FastString类的构造,应该用 #include "FastString.h" 包含头文件的方法来访问,并不是直接把两个头文件的内容都写在一起。。。好吧我承认是我在偷懒,,,刚开始是分开放的但是有很多报错然后就。。。


采用句柄类把接口与实现相分离,使得用户与对象之间形成一道精密的协议,用户只有通过接口类才能实现与对象之间的通信,它不依赖于实现类的任何细节。

但这种方法也有缺点:接口类必须把每个方法调用显式的传递给实现类,简单的类接口少,复杂的就会很麻烦。所以这个方法并没有完全解决这个问题。

---------------------------------------------------------------------------------------------------------------


通过将C++对象封装到DLL中,客户需重用对象只需链接DLL并包含相应的头文件和.lib文件即可,客户所见即接口文件中类的声明,从而使实现代码有效保护起来。但c++方法还具有这样的问题,对象的实现细节都包含在类的声明中,对于对象的私有成员客户不可以访问但仍然可以看的一清二楚。实际客户希望从对象那里获得的只是成员函数的地址。所以可建立一个只包含所有引用成员函数地址指针的表,客户调用函数时,只需简单的查找这个表活的函数的地址然后跳转到该地址执行即可。这里,c++抽象基类可以很好的解决这一问题,因为编译器回味抽象类建立一个包含所有成员函数的函数表。(这里不清楚的同学可以戳下面的链接Y(^_^)Y记得点赞哦!)
c++继承和多态:
http://blog.csdn.net/cherry_ermao/article/details/51105450

再回到这个例子上,通过抽象类创建的IFaststring类:


// The following ifdef block is the standard way of creating macros which make exporting 
// from a DLL simpler. All files within this DLL are compiled with the IFASTSTRING1_EXPORTS
// symbol defined on the command line. this symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see 
// IFASTSTRING1_API functions as being imported from a DLL, wheras this DLL sees symbols
// defined with this macro as being exported.
#ifdef IFASTSTRING1_EXPORTS
#define IFASTSTRING1_API __declspec(dllexport)
#else
#define IFASTSTRING1_API __declspec(dllimport)
#endif

// This class is exported from the IFastString1.dll
class IFASTSTRING1_API CIFastString1 {
public:
//	CIFastString1(void);
	// TODO: add your methods here.
	virtual int Length(void) const=0;
	virtual char* Find(const char*psz)const=0;
};


class FastString : public CIFastString1  //派生于接口类 
{
	const int m_cch;
	char*m_psz;
public:
	FastString(const char* psz);
	~FastString();
	int Length(void)const;  //不需要加上virtual 关键字
	char* Find(const char*psz)const;//覆盖了基类的虚函数
}; 

extern "C"{      __declspec(dllexport) 	
             CIFastString1 *CreateFastString(const char*psz);}//导出函数为接口类的指针
extern IFASTSTRING1_API int nIFastString1;

IFASTSTRING1_API int fnIFastString1(void);

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

#include "stdafx.h"
#include "IFastString1.h"

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 an example of an exported variable
IFASTSTRING1_API int nIFastString1=0;

// This is an example of an exported function.
IFASTSTRING1_API int fnIFastString1(void)
{
	return 42;
}

// This is the constructor of a class that has been exported.
// see IFastString1.h for the class definition
// CIFastString1::CIFastString1()
// { 
// 	return; 
// }

CIFastString1 * CreateFastString(const char * psz)
{return new FastString(psz);}  //创建一个实现类的实例. 返回值是接口指针.通过基类指针才可以调用派生类函数

FastString::FastString(const char* psz)
:m_cch(strlen(psz)), m_psz(new char[m_cch+1])
{strcpy(m_psz,psz);}


FastString::~FastString(void)
{ delete []m_psz;}   // 释放成员变量占用的内存.

int FastString::Length(void) const{
	return m_cch;}

char* FastString::Find(const char*psz)const
{
	return strstr(m_psz,psz);
}






---------------------------------------------------------------------------------------------------------------


  • 用一个基类指针pIFS指向一个子类对象。delete pIFS;将导致基类的析构函数被调用.而实现类(派生类)中所动态分配的保存字符串的内存将不能得到及时释放.造成内存泄漏问题
  • 简单的解决方法1:
  • 把基类的析构函数声明为虚的.这样,派生类的析构函数也是虚的.执行delete pIFS;,由于pIFS指向的是派生类的对象,所以调用的是派生类的析构函数.可以完整地释放派生类对象所占用的存储空间。但是如果将接口类的析构函数做成虚的,会破坏接口类的编译器独立性。因为虚析构函数在虚表中的位置随着编译器的不同而不同。
  • 解决方法2
  • 给接口类增加一个Delete方法,作为其另一个纯虚函数,在派生类中实现自身的删除,以导致正确的析构过程。

// The following ifdef block is the standard way of creating macros which make exporting 
// from a DLL simpler. All files within this DLL are compiled with the IFASTSTRINGD_EXPORTS
// symbol defined on the command line. this symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see 
// IFASTSTRINGD_API functions as being imported from a DLL, wheras this DLL sees symbols
// defined with this macro as being exported.
#ifdef IFASTSTRINGD_EXPORTS
#define IFASTSTRINGD_API __declspec(dllexport)
#else
#define IFASTSTRINGD_API __declspec(dllimport)
#endif

// This class is exported from the IFastStringD.dll
class IFASTSTRINGD_API CIFastStringD {
public:
	//CIFastStringD(void);
	// TODO: add your methods here.
    virtual void Delete(void)=0;
	virtual int Length(void) const=0;//没有实现的虚函数,典型的纯虚函数
	virtual char* Find(const char*psz)const=0;

};


class FastString : public CIFastStringD  //派生于接口类
{
//	const int m_cch;
	char*m_psz;
public:
	FastString(const char* psz);
	~FastString();
	void Delete(void);
	int Length(void)const;  //不需要加上virtual 关键字
	char* Find(const char*psz)const;//覆盖了基类的虚函数
};

extern "C"{      __declspec(dllexport) 	
             CIFastStringD *CreateFastString(const char*psz);}//导出函数返回值为接口类的指针
extern IFASTSTRINGD_API int nIFastStringD;

IFASTSTRINGD_API int fnIFastStringD(void);


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

#include "stdafx.h"
#include "IFastStringD.h"
#include
   
   
    
    

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 an example of an exported variable
IFASTSTRINGD_API int nIFastStringD=0;

// This is an example of an exported function.
IFASTSTRINGD_API int fnIFastStringD(void)
{
	return 42;
}

// This is the constructor of a class that has been exported.
// see IFastStringD.h for the class definition
// CIFastStringD::CIFastStringD()
// { 
// 	return; 
// }

CIFastStringD * CreateFastString(const char * psz)
{return new FastString(psz);}  //创建一个实现类的实例. 返回值是接口指针.


void FastString::Delete()
{ delete this; }   //由用户调用,删除自身.

FastString::~FastString(void)
{ delete []m_psz;}   // 由上一个函数引起,释放成员变量占用的内存.
 //构造函数, Length Find 等不变,略.
/
// FastString::FastString(const int ch):m_cch(ch)
// { 
//  	return; 
// }
FastString::FastString(const char* psz):m_psz(new char[strlen(psz)+1])
{strcpy(m_psz,psz);}  //分配内存

int FastString::Length(void) const{
	return strlen(m_psz);}  //计算长度

char* FastString::Find(const char*psz)const
{
	return strstr(m_psz,psz);
} //查找子串

   
   



从C++过度到com需要经历的过程

实现接口的引用计数

对象允许多个接口

类厂对象使用标准IClassFactory接口

使用_stdcall调用约定

实现DLL动态卸载

实现对象自注册


声明:文中所提及的源码都是在动态链接库下实现的,所以会有些看起来奇怪的宏注释之类的,还有命名可能会有些奇怪,我发现所有构建好的类动态库会自动在其前面加上一个C,例如CFaststring,如果你在VC下按照上面的步骤同样建立动态链接库的话,会看到这些代码是如何出来的。。。。本文章仅供参考,如发现问题欢迎留言骚扰( ̄▽ ̄)


  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
组件基础 1 软件开发的阶段 1.1 结构化编程 采用自顶向下的编程方式,划分模块 和功能的一种编程方式。 1.2 面向对象编程 采用对象的方式,将程序抽象成类, 模拟现实世界,采用继承、多态的方式 设计软件的一种编程方式。 1.3 面向组件编程 将功能和数据封装成二进制代码,采用 搭积木的方式实现软件的一种编程方式。 2 组件和优点 2.1 组件 - 实际是一些可以执行的二进 制程序,它可以给其他的应用程序、操 作系统或其他组件提供功能 2.2 优点 2.2.1 可以方便的提供软件定制机制 2.2.2 可以很灵活的提供功能 2.2.3 可以很方便的实现程序的分布式 开发。 3 组件的标准 - COMComponent Object Model ) 3.1 COM是一种编程规范,不论任何开发语言 要实现组件都必须按照这种规范来实现。 组件和开发语言无关。 这些编程规范定义了组件的操作、接口的 访问等等。 3.2 COM接口 COM接口是组件的核心,从一定程度上 讲"COM接口是组件的一切". COM接口给用户提供了访问组件的方式. 通过COM接口提供的函数,可以使用组件 的功能. 4 COM组件 4.1 COM组件-就是在Windows平台下, 封装在动态库(DLL)或者可执行文件(EXE) 中的一段代码,这些代码是按照COM的 规范实现. 4.2 COM组件的特点 4.2.1 动态链接 4.2.2 与编程语言无关 4.2.3 以二进制方式发布 二 COM接口 1 接口的理解 DLL的接口 - DLL导出的函数 类的接口 - 类的成员函数 COM接口 - 是一个包含了一组函数指针 的数据结构,这些函数是由组件实现的 2 C++的接口实现 2.1 C++实现接口的方式,使用抽象类 定义接口. 2.2 基于抽象类,派生出子类并实现 功能. 2.3 使用 interface 定义接口 interface ClassA { }; 目前VC中,interface其实就是struct 3 接口的动态导出 3.1 DLL的实现 3.1.1 接口的的定义 3.1.2 接口的实现 3.1.3 创建接口的函数 3.2 DLL的使用 3.2.1 加载DLL和获取创建接口的函数 3.2.2 创建接口 3.2.3 使用接口的函数 4 接口的生命期 4.1 问题 在DLL中使用new创建接口后,在用户 程序使用完该接口后,如果使用delete 直接删除,会出现内存异常. 每个模块有自己的内存堆(crtheap) EXE - crtheap DLL - crtheap new/delete/malloc/free默认情况 下都是从自己所在模块内存堆(crtheap) 中分配和施放内存.而各个模块的 这个内存堆是各自独立.所以在DLL中 使用new分配内存,不能在EXE中delete. 4.2 引用计数和AddRef/Release函数 引用计数 - 就是一个整数,作用是 表示接口的使用次数 AddRef - 增加引用计数 +1 Release - 减少引用计数 -1, 如果 当引用计数为0,接口被删除 4.3 使用 4.3.1 创建接口 4.3.2 调用AddRef,增加引用计数 4.3.3 使用接口 4.3.4 调用Release,减少引用计数 4.4 注意 4.4.1 在调用Release之后,接口指针 不能再使用 4.4.2 多线程情况下,接口引用计数 要使用原子锁的方式进行加减 5 接口的查询 5.1 每个接口都具有唯一标识 GUID 5.2 实现接口查询函数 QueryInterface 6 IUnknown 接口 6.1 IUnknown是微软定义的标准接口 我们实现所有接口就是继承这个接口 6.2 IUnknown定义了三个函数 QueryInterface 接口查询函数 AddRef 增加引用计数 Release 减少引用计数 7 接口定义语言 - IDL(Interface Definition Language ) 7.1 IDL和MIDL IDL - 定义接口的一种语言,与开发 语言无关. MIDL.EXE - 可以将IDL语言定义接口, 编译成C++语言的接口定义 7.2 IDL的基础 import "XXXX.idl" [ attribute ] interface A : interface_base { } 7.2.1 Import 导入,相当于C++的 #include 7.2.2 使用"[]"定义区域,属性描述 关键字 1) object - 后续是对象 2) uuid - 定义对象GUID 3) helpstring - 帮助信息 4) version - 版本 5) point_default - 后续对象 中指针的默认使用方式 比如: uniqune - 表示指针可以 为空,但是不能修改 7.2.3 对象定义 1) 父接口是IUnknown接口 2) 在对象内添加函数,函数定义必须 是返回 HRESULT. HRESULT是32位整数,返回函数是否 执行成功,需要使用 SUCCESSED和 FAILED宏来判断返回值.
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值