1.用MIDL语言在.idl中定义结构:
typedef struct
{
unsigned short code1;
unsigned short code2;
unsigned short code3;
unsigned short code4;
}SIPAddress;
[helpstring("method RegEdit")] HRESULT RegEdit([in] USHORT unServerType, [in] ULONG ulInputPort, [in] ULONG ulOutputPort, [in ] SIPAddress* sIpAddress, [in] USHORT unAct);
其实,在xxx(工程).h中,此结构是被这样定义的:
typedef /* [public][public] */ struct __MIDL___MIDL_itf_portmapping_0000_0001
{
unsigned short code1;
unsigned short code2;
unsigned short code3;
unsigned short code4;
} SIPAddress;
可以看出,midl语言中定义结构的特点,而且要在.idl文件中使用此结构的话只能在.idl中用midl语言写这个结构。但在此com对象里面也可以使用这个结构。
2.Com接口方法不能传递数组。解决方法:
(1)在.idl中声明的时候:
(....., [ in, size_is( IPTotalSize ) ]BYTE* pIPAddress, ULONG ulIPTotalSize, ....)
在接口方法实现的时候:
(......, BYTE* pIPAddress, 4*USHORT, ....)
在.idl中声明的时候,其实就是传了一块内存中IPTotalSize大小的空间,而pIPAddress是指向这块空间的起始的指针。(具体size_is的功能见msdn)
(2)在.idl中定义一个结构(结构中每个元素变量对应数组中一个成员)。然后在传递的时候用指向此结构的指针。
3.C#没有了指针,在引用COM组建的时候
由于com接口方法不能使用数组,C#又不能使用指针,所以这时候只能定义结构来解决。在c#工程中引用com组件,此时vs.net2003会做好一些封装工作。(1)封装好了实现接口的类:”com组件中的对象名”+”Class”。(所以在c#中直接用这个类来调用要使用的com对象的函数。(2)对在.idl定义的结构也进行了继承(所以在c#中也可以直接使用这个结构来进行附值和处理)。但与c++不同的是,不能用指针,所以应该写成如下形式:
SIPAddress sIpAddress = new SIPAddress();
ro_1.RegEdit( unServerType, uInputPort, uOutputPort, ref sIpAddress, unact );
可以看出来,这里sIpAddress是一个SIPAddress结构的对象,传递的时候也是传递对象的地址。
4.COM组件中的GUID问题。
在COM组件中有3处要用到GUID:COM接口,COM对象,COM组件库(这3个当然也都是自己写的程序了~只不过ATL会给做好这些工作。)
它们分别被用在以下文件中:xxx(工程名).h;xxx(COM对象).rgs;xxx(工程名)_i.c。所以如果想自己再生成新的GUID来取代原来的话,需要同时改这3个地方。
5.手动注册COM组件
在包含xxx.dll(此com组件的封装)的目录下:regsvr32.exe xxx.dll。就可以了
6.COM组件dll与普通dll区别和它在ASP.NET中引用要注意的问题
因为COM组件DLL是编译成2进制存贮到机器里的,同时也在本地计算机的注册表上进行了GUID的注册。所以,如果自己想写个.exe来运行它的功能,不用再包含.Lib和把.DLL放到.exe的文件夹下了。只需在.exe工程中包含必须的ATL的头文件,然后使用CoCreateInstance(…)就可以调用想要的COM接口和COM对象了~!
但在如ASP.NET工程中,就需要使用vs.net2003的引用功能,先来引用此COM组件。然后直接使用vs.net2003给封装好的类就可以使用COM组件的功能了。对了,记住,还要引用它给你创建好的此组件的名字空间。
还要注意,如果需要此COM组件在ASP.NET中完成网络功能(就是客户和服务器通过网络来交流信息的时候)之前先要编译xxx(COM组件工程)PS,因为这样它会为xxx工程添加Proxy和Stub功能,在xxx.h中有定义。