惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
CXSECURITY Database RSS Feed - CXSecurity.com
Stack Overflow Blog
Stack Overflow Blog
月光博客
月光博客
T
Threat Research - Cisco Blogs
小众软件
小众软件
有赞技术团队
有赞技术团队
酷 壳 – CoolShell
酷 壳 – CoolShell
Apple Machine Learning Research
Apple Machine Learning Research
C
Cyber Attacks, Cyber Crime and Cyber Security
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
T
Tailwind CSS Blog
Cisco Talos Blog
Cisco Talos Blog
V
V2EX
博客园 - 【当耐特】
C
Cybersecurity and Infrastructure Security Agency CISA
Hugging Face - Blog
Hugging Face - Blog
The Cloudflare Blog
The Last Watchdog
The Last Watchdog
Simon Willison's Weblog
Simon Willison's Weblog
T
Threatpost
S
Secure Thoughts
O
OpenAI News
P
Proofpoint News Feed
S
SegmentFault 最新的问题
Forbes - Security
Forbes - Security
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Application and Cybersecurity Blog
Application and Cybersecurity Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Last Week in AI
Last Week in AI
宝玉的分享
宝玉的分享
Scott Helme
Scott Helme
T
Tenable Blog
A
Arctic Wolf
L
LINUX DO - 热门话题
爱范儿
爱范儿
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
www.infosecurity-magazine.com
www.infosecurity-magazine.com
V
Visual Studio Blog
Hacker News: Ask HN
Hacker News: Ask HN
Hacker News - Newest:
Hacker News - Newest: "LLM"
腾讯CDC
博客园 - Franky
WordPress大学
WordPress大学
Know Your Adversary
Know Your Adversary
博客园_首页
雷峰网
雷峰网
IT之家
IT之家
PCI Perspectives
PCI Perspectives
L
LINUX DO - 最新话题
H
Heimdal Security Blog

博客园 - 悠然小调

nothing.... Ogre中在SceneNode节点旁显示二维字的代码 博文阅读密码验证 - 博客园 最简单的智能指针原理 模板的特化 计算基类虚表指针在派生类中的偏移量 写一个内存拷贝函数 [转]来自 COM 经验的八个教训 winsock中select的作用 windows核心编程学习笔记(三)线程池(Thread Pooling) windows核心编程学习笔记(八)结构化异常处理(Structured Exception Handling) [转]亲密接触VC6.0编译器 windows核心编程学习笔记(七)DLL Injection and API Hooking windows核心编程学习笔记(五.续)堆 windows核心编程学习笔记(五)内存映射文件 windows核心编程学习笔记(四)windows内存结构/虚拟内存/线程的堆栈 windows核心编程学习笔记(二)Wait For Kernel Object(s) windows核心编程学习笔记(一)使用Critical Section [转]筛选法求素数
COM本质论学习笔记(一)IDL
悠然小调 · 2008-03-11 · via 博客园 - 悠然小调

IDL是Interface Definition Language的所写,翻译为接口定义语言

1.该语言规定,必须显式的为每个接口函数指定参数的目的,例如
HRESULT foo([in]long* Input, [out]long* Output, [in, out]long* InAndOut);

2.通常,函数的返回值为HRESULT,表示执行的状况,以便被其他语言所捕获,例如Visual Basic等。HRESULT大体分为三个部分:

31|30 29|28 ... 16|15 ...0
成 | 保留 |   操作码 | 信息码



第31位如果是0那么代表成功,否则代表失败,这也是Win32 SDK的SUCCESSED宏判断的依据:
#define SUCCESSED(hr) (long(hr) >= 0)
#define FAILD(hr) (long(hr) < 0)

3.该返回值只提供了函数的执行情况,函数可以另外提供返回值:
HRESULT foo([in]long* Input, [out]long* Output, [out, retval]long* InAndOut);
该函数在VB里看起来应该是这样的(凭记忆,未验证):
Public Declare Function foo(ByVal Input as Integer, ByRef Output as Integer) as Integer
如果在VB中调用该函数失败了,那么不是通过返回值把错误码返回,而是VB的解释器触发一个异常,你需要在VB里用On Error xxxx来进行错误处理。

4.声明一个接口。接口的声明是如下形式滴~
[object, uuid(00000000-0000-0000-0000-000000000000)]
interface IMyInterface : IBaseInterface
{
    enum MyEnum
    {
        ME_aa,
        ME_bb,
    }
    typedef struct _ASTRUCT
    {
        MyEnum me;
        long val;
    }
    HRESULT foo1([in]LONG* Input, [out, retval]RetVal);
}

[]中的部分是接口属性,其中object代表这是一个com接口,后面的部分是全局唯一标识符(GUID),当用在com接口时,也叫做接口标识符(IID)。

接下来IMyInterface是接口名,IBaseInterface是基接口名
{}中则是接口体。

5.细说GUID\IID\CLSID
GUID是个128位的大数,所以COM用一个结构体来表示GUID
typedef struct _GUID
{
    DWORD  Data1;
    WORD    Data2;
    WORD    Data3;
    BYTE      Data4[8];
}GUID;
你看 (4+2+2+8)*8=128.
同时,还有如下定义:
typedef GUID IID;
typedef GUID CLSID;

所以说,IID,CLSID和GUID都是一种东东。
有时为了判断2个GUID是否相等,那么用引用就会很高效,所以还有如下宏定义,以及== 和 !=操作符:
#define REFGUID   const GUID&
#define REFIID      const IID&
#define REFCLSID  const CLSID&

这个GUID/IID通常用VCSDK附带的GUIDGEN.EXE来生成,理论上不会重复~

6.结构体与联合体
在IDL中也可以声明结构体和联合体
typedef struct _TestStruct
{
    long a;
    short b;
}TESTSTRUCT;

struct TESTSTRUCT2
{
    long a;
    short b;
};

union VALUE
{
    [case(1)]long a;
    [case(2)]short b;
};

也可以在结构体或者函数中使用联合:
struct TESTSTRUCT3
{
    short t;
    [switch_is(t)]union VALUE
    {
        [case(1)]long a;
        [case(2)]short b;
    };
};

HRESULT foo1([in, switch_is(t)]union VALUE* pu, [in]short t);

7.属性
给接口添加属性,可以使用户感觉更良好:
[object, uuid(...)]
interface IPropertyInterface : IUnknown
{
    // 只读
    [propget] HRESULT Age([out, retval]long* RetVal);

    // 读写
    [propput] HRESULT ID([in]long id);
    [propget] HRESULT ID([out, retval]long* id);
}
实现这样的接口也比较容易,只需要在C++类对应的方法前加get_或者put_即可
class CPropertyInterface : public IPropertyInterface
{
    public:
    ....
    HRESULT get_Age(long* RetVal);
    HRESULT get_ID(long* RetVal);
    HRESULT put_ID(long id);
}