在COM组件中,怎样把自定义的结构体作为,其接口方法的参数呢?
我是用MFC写的组件,DATA是我在.H中定义的一个结构,我要把SendList(DATA &data,DWORD n)变成COM接口方法,应该怎样做呀? 问题点数:30、回复次数:13Top
1 楼atEleven(@十一)回复于 2003-09-04 20:50:59 得分 24
1 一个标准的方法是: 把DATA写成一个Automation对象(从CCmdTarget继承)
2
如果你能保证组件是进程内组件(DLL),且只被单线程调用,可以把结构体指针当做一个LONG型数字传给客户端,反之(从客户端返回)亦然.比如说vb作为客户端:
dim a as DATA
a.member1 = 1
a.member2 = 2
call Obj.SendList(varPtr(a),n) '请注意这里使用varPtr函数传指针.
3
可以把结构体数据压缩至一个SAFEARRAY中.或者当做字节序列(BYTE ARRAY)压缩至SAFEARRAY中.
关于这个问题,http://www.microsoft.com/msj/0696/activex0696.aspx 有很详细的描述,是英文.我自己也做过类似的问题.有时间我们可以交流.
Top
2 楼atEleven(@十一)回复于 2003-09-04 20:56:03 得分 0
另:如果是ATL(支持双接口)可以参考这篇文档.
http://www.codeproject.com/atl/udtdemo.aspTop
3 楼ISAKEEPER()回复于 2003-09-07 15:10:52 得分 0
to atEleven(@十一):您好!
我现在想用第一种方法
具体步骤:
CCommunication是从CCmdTarget继承,且在CCommunication.h中include DATA.h,DATA在DATA.h中定义的。这样生成了一个ICCommunication接口,然后选择这个接口,添加方法(SendList),在选择方法参数类型时,没有DATA;如果手工修改的话,编译不过。
E:\myprg\CommLan_0906\Communication.cpp(66): DISP_FUNCTION(CCommunication, "SendList", SendList, VT_BOOL, VTS_I2 VTS_I2)//关键这个地方“VTS_I2 VTS_I2”不知怎样修改?
E:\myprg\CommLan_0906\Communication.cpp(293):BOOL CCommunication::SendList(DATA data, short m)
E:\myprg\CommLan_0906\Communication.h(88): afx_msg BOOL SendList(DATA data, short m);
3 occurrence(s) have been found.
请详细指点,谢谢!
Top
4 楼atEleven(@十一)回复于 2003-09-07 16:43:20 得分 0
如果需要,我可以提供CData 的实现样例.
//====idl或odl文件================================================
//以Data作为automation对象出现在在IDL/ODL文件中.
library Your_Lib
{
......
//把struct DATA包装为自动化对象,需要手工实现类class CData : public CCmdTarget
//下面是 dispatch interface
[ uuid(E8E62570-B183-4976-83C8-55DDAA3CF0C0) ]
dispinterface IData
{
properties:
[id(1), helpstring("属性 ldata")] LONG ldata;
[id(2), helpstring("属性 sdata")] BSTR sdata;
methods:
};
//下面是 automation class 的IDL声明
[ uuid(2A36D675-D176-4E3F-A93A-3D172C69EA57) ]
coclass AutoData
{
[default] dispinterface IData;
};
......
}
//==== 头文件================================================
// 需要调用以 struct Data 为参数的函数的类头文件.
class CCall : public CCmdTarget
{
......
void SetData(IDispatch* data);
}
//==== cpp 文件================================================
// 需要调用以 struct Data 为参数的函数的类cpp文件
DISP_FUNCTION_ID(Cax1Ctrl, "SetData", dispidSetData, SetData, VT_EMPTY, VTS_DISPATCH)
void CCall::SetData(IDispatch* data)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
//这个函数得到struct Data,需要手工实现
//可以通过类CData和接口IDispatch的指针偏移量得到.
DATA* pData = CData::GetDataFromIDisp(data);
//无需释放pData指针
}
Top
5 楼atEleven(@十一)回复于 2003-09-07 16:50:25 得分 0
还有,在ODL文件中定义了IData之后,可以手工修改SetData的IDispatch为IData
这样在生成的类型库文件中(比如说vb中打开)可以直接识别IData自动化接口.
[id(1), helpstring("方法SetData")] void SetData(IData* data); //这里.
vb中可以这样调用:
dim objdata as AutoData //AutoData是ODL文件中coclass的名字
set objdata = new AutoData
objdata.ldata = 100
objdata.sdata = "some string"
objCall.SetData objdata
Top
6 楼Microsoftadherent(王万新)回复于 2003-09-08 09:46:40 得分 1
在《COM精彩编程实例》中有一个专门的例子。Top
7 楼XXandOO(麦猪)回复于 2003-09-08 11:18:21 得分 5
如果客户是C++程序可在idl文件中定义这个结构体,并使用其作为借口函数的参数;如果客户是vb或脚本语言,则借口函数的参数须是OLE变量,一般来说使用idispatch/idispatch*作为参数类型。Top
8 楼ISAKEEPER()回复于 2003-09-08 13:08:38 得分 0
TO XXandOO(麦猪):
我是用MFC写的COM
to atEleven(@十一):您好!
我按照你的提示试验了一下,还是有以下错误:
我在Communication.h中定义了
bool SendList(IDispatch* data,DWORD );但还是出错啊
E:\myprg\ComLan0908\Communication.cpp(60) : error C2065: 'dispidSetData' : undeclared identifier
E:\myprg\ComLan0908\Communication.cpp(283) : error C2511: 'SendList' : overloaded member function 'bool (struct IDispatch *,short)' not found in 'CCommunication'
e:\myprg\comlan0908\communication.h(45) : see declaration of 'CCommunication'
Error executing cl.exe.Top
9 楼atEleven(@十一)回复于 2003-09-08 13:20:42 得分 0
需要定义dispid的啊.我给的都不是直接能编译的东东.Top
10 楼ISAKEEPER()回复于 2003-09-08 15:05:58 得分 0
我把所有与SendList()相关的语句写在下面,请帮我看看,谢谢
E:\myprg\ComLan0908\Communication.cpp(60): DISP_FUNCTION_ID(CCommunication, "SendList", IData, SendList, VT_BOOL, VTS_DISPATCH VTS_I2)
E:\myprg\ComLan0908\Communication.cpp(282):bool CCommunication::SendList(IData* data,short n)
E:\myprg\ComLan0908\Communication.h(89): afx_msg BOOL SendList(IData* data,DWORD );
// Class information for CCommunication
[ uuid(3331CA64-3A34-4EE4-91A2-01125C196CFC) ]
coclass Communication
{
[default] dispinterface ICommunication;
};
// Class information for CData
[ uuid(E26B75C9-6724-420F-A54B-CF77E89D0BCE) ]
coclass Data
{
[default] dispinterface IData;
};
编译之后
E:\myprg\ComLan0908\ComLan0908.odl(31) : error MIDL2025 : syntax error : expecting a type specification near "IData"
E:\myprg\ComLan0908\ComLan0908.odl(31) : error MIDL2026 : cannot recover from earlier syntax errors; aborting compilation
Error executing midl.exe.Top
11 楼atEleven(@十一)回复于 2003-09-08 16:14:25 得分 0
IData只是在ODL中定义,而不需要在h和cpp文件中定义。
IData需要在所有引用该接口前的地方定义。
我还是给你一个例子自己看吧。
Top
12 楼ISAKEEPER()回复于 2003-09-08 19:29:19 得分 0
谢谢啦 :)Top
13 楼ISAKEEPER()回复于 2003-09-14 09:51:12 得分 0
问题解决,但我是这样解决的
用LPDISPATCH * 类型,来实现中间的转换的Top




