在RPC的应用里,经常在接口方法中使用结构类型,COM的方法中也可以传递结构类型。就用一个实验简单测试一下在COM方法中传递结构类型。
用ATL向导建立一个名字为structsmp的工程,加入一个简单对象MyTest继承接口名为ITestStruct。.
在工程中加入一个文件mytypes.idl,在里面定义一个结构UserInfo如下:
typedef struct
{
long no;
unsigned char name[255];
BSTR address;
}UserInfo;
在structsmp.idl的文件头部加入import “mytypes.idl”
1. 加入第一个方法GetUserInfo
HRESULT GetUserInfo([out,retval] UserInfo *pUserInfo);
方法的实现如下:
STDMETHODIMP CMyTest::GetUserInfo(UserInfo *pUserInfo)
{
pUserInfo-> no=100;
memcpy(pUserInfo-> name, "Mona Lisa ",10);
pUserInfo-> address=SysAllocString(L "Italy ");
return S_OK;
}
下面用VB程序作为客户端来测试这个方法:
新建一个VB的工程,引用此组件。定义组件对象:
Dim obj As New STRUCTSMPLib.MyTest
下面调用方法如下:
Dim ui As userinfo
ui = obj.GetUserInfo()
MsgBox ui.no
MsgBox StrConv(ui.Name, vbUnicode)
MsgBox ui.address
运行的结果符合了我们的期望,这个实验已经踏出坚实的第一步了。
2.下面在组件里添加第二个方法:
HRESULT SetUserInfo([in] UserInfo *pUserInfo);
STDMETHODIMP CMyTest::SetUserInfo(UserInfo *pUserInfo)
{
USES_CONVERSION;
char info[255];
WriteLog( "begin SetUserInfo function ");
sprintf(info, "pUserInfo-> no is:%d,pUserInfo-> name is:%s,pUserInfo-> address is:%s ",pUserInfo-> no,pUserInfo-> name,OLE2T(pUserInfo-> address));
WriteLog(info);
return S_OK;
}
WriteLog函数是一个把信息写进文件的函数。
在VB的客户程序里:
Dim ui As userinfo
ui.no = 101
ui.Name(0) = Asc( "h ")
ui.Name(1) = Asc( "e ")
ui.Name(2) = Asc( "l ")
ui.Name(3) = Asc( "l ")
ui.Name(4) = Asc( "o ")
ui.address = "world "
obj.SetUserInfo ui
查看最终的结果,又是正确的,这次的结果让人信心倍增。
3.从现在来看对单个结构在接口方法里传递没有任何的问题,下面就是该考虑结构数组的时候了,一口气添加两个方法,请看:
在接口里添加两个方法,传递结构数组,并且在方法的实现里写上测试的代码。
HRESULT SetUserInfoArray([in] long cMax,[in,size_is(cMax)] UserInfo *pUserInfo);
HRESULT GetUserInfoArray([in] long cMax,[out,size_is(cMax)] UserInfo *pUserInfo);
STDMETHODIMP CMyTest::SetUserInfoArray(long cMax, UserInfo *pUserInfo)
{
USES_CONVERSION;
char info[255];
WriteLog( "begin SetUserInfoArray function ");
for(int i=0;i <cMax;i++)
{
sprintf(info, "%d:pUserInfo-> no is:%d,pUserInfo-> name is:%s,pUserInfo-> address is:%s ",i+1,pUserInfo-> no,pUserInfo-> name,OLE2T(pUserInfo-> address));
WriteLog(info);
pUserInfo++;
}
return S_OK;
}
STDMETHODIMP CMyTest::GetUserInfoArray(long cMax, UserInfo *pUserInfo)
{
for(int i=0;i <cMax;i++)
{
pUserInfo-> no=100;
memcpy(pUserInfo-> name, "Mona Lisa ",10);
pUserInfo-> address=SysAllocString(L "Italy ");
pUserInfo++;
}
return S_OK;
}
现在在VB的客户程序里加上测试这两个方法的代码:
Dim ui(9) As userinfo
obj.GetUserInfoArray 10, ui(0)
For i = 0 To 9
Debug.Print ui(i).no
Debug.Print StrConv(ui(i).Name, vbUnicode)
Debug.Print ui(i).address
Next
和
Dim ui(9) As userinfo
For i = 0 To 9
ui(i).no = 101
ui(i).Name(0) = Asc( "h ")
ui(i).Name(1) = Asc( "e ")
ui(i).Name(2) = Asc( "l ")
ui(i).Name(3) = Asc( "l ")
ui(i).Name(4) = Asc( "o ")
ui(i).address = "world "
Next
obj.SetUserInfoArray 10, ui(0)
ACTION的结果可以说让我们欣喜若狂,结构类型在接口里畅通无阻。
4.远程调用
狂喜过后我们又要进行下一步的实验,这一次针对的是结构类型的方法在远程调用中的特性。在这里我们使用系统提供的代理dllhost.exe和标准调度,客户程序是一个控制台程序。这一次结构类型又不负众望顺利过关,表现的非常完美。到此实验就OVER了,以后可以放心大胆的在COM的方法里使用结构类型啦。