com使用自定义数据类型(UDT) [转]

来源:互联网 发布:芭芭拉史翠珊 知乎 编辑:程序博客网 时间:2024/05/17 05:55
十分感谢你详细的解答,让我弄明白了不少东西!我是COM的初学者,虽然看了《COM 本质论》之类的书,不过都是看着时觉得有道理,好像明白了什么!真动手作东西时还是想法转不过弯来!现在感觉对接口的用处体会深了一点。
    不过你说SafeArray中的元素不能使用struct这种数据类型,我有点疑惑。我在接口中有这么个函数就是传SAFEARRAY的,元素是自定义的结构。在VB中调用该接口函数也可以成功。
结构定义及函数代码如下:
IDL:
  typedef [uuid(5536B87A-57D7-45e3-8A06-9B21BE40F5D2)] struct rcSimu
  {
         int iSimuNo;
 BSTR strSimuName;
  }CRcSimu;
 
  typedef [uuid(425091B5-1E6F-4cfb-995C-18AFA20AFA84)] struct rcNode
  {
        int  iUniqueNo;
        float   fResult;
        BSTR  strNodeName;
        SAFEARRAY(CRcSimu) aRcSimu; 
  }CNode;
 

函数:

/*自定义结构的ID*/
const GUID IID_STRUCT_SIMU = { 0x5536b87a, 0x57d7, 0x45e3, { 0x8a, 0x6, 0x9b, 0x21, 0xbe, 0x40, 0xf5, 0xd2 } };
const IID IID_STRUCT_NODE = { 0x425091b5, 0x1e6f, 0x4cfb, { 0x99, 0x5c, 0x18, 0xaf, 0xa2, 0xa, 0xfa, 0x84 } };

STDMETHODIMP CRcTest::GetStruct(SAFEARRAY **pNode)
{
   IRecordInfo* pRecordInfo=NULL;
   IRecordInfo *pSimuRecordInfo=NULL;

   HRESULT  hR=GetRecordInfoFromGuids(LIBID_RECON_ATLLib,
                      1,0,GetUserDefaultLCID(),IID_STRUCT_SIMU
                      ,&pSimuRecordInfo);
                            
   if(!SUCCEEDED(hR))
   {
      return FALSE;
   }
   hR=GetRecordInfoFromGuids(LIBID_RECON_ATLLib
                      ,1,0,GetUserDefaultLCID(),IID_STRUCT_NODE
                      ,&pRecordInfo);
   if(!SUCCEEDED(hR))
   {
      return FALSE;
   }

   /*创建大小为5个元素的自定义结构的数组--该结构内还有成员为数组*/
   *pNode=SafeArrayCreateVectorEx(VT_RECORD,0,5
                                 ,(void *)pRecordInfo);
   CNode *pData=0;
   hR=SafeArrayAccessData(*pNode,(void **)&pData);
   if(!SUCCEEDED(hR))
   {
      return FALSE;
   }
   CRcSimu *pSimu=NULL;
   for(int i=0;i<5;i++)
   {
      pData[i].iUniqueNo=i*100*(i+1);
      pData[i].fResult=2.2343+i;
     
      /*(CNode 结构的aRcSimu为数组类型) 动态创建aRcSimu的大小*/
      pData[i].aRcSimu=SafeArrayCreateVectorEx(VT_RECORD,0,3,(void *)pSimuRecordInfo);
      hR=SafeArrayAccessData(pData[i].aRcSimu,(void **)&pSimu);
      for(int j=0;j<3;j++)
      {
         pSimu[j].iSimuNo=(i+1)*10+(j+1);
      }
      SafeArrayUnaccessData(pData[i].aRcSimu);
   }
 
   SafeArrayUnaccessData(*pNode);
   pSimuRecordInfo->Release();
   pRecordInfo->Release();
   return S_OK;
}
下面是VB中的测试函数,在里面动态分配了数组大小,
    Dim aSimu() As RECON_ATLLib.rcSimu   
    Dim i, j, iSum As Integer
    Dim objRcTest As RECON_ATLLib.RcTest
    Set objRcTest = New RECON_ATLLib.RcTest

    Dim aNodes() As RECON_ATLLib.rcNode
    objRcTest.GetStruct aNodes
    i = UBound(aNodes)
    MsgBox "在VC里分配的数组大小为" + CStr(i+1)
    MsgBox aNodes(i).fResult
    i = UBound(aNodes(0).aRcSimu)
    For j = 0 To i
       MsgBox "节点1的aRcSimu(" + CStr(j) + ").iSimuNo="
       + CStr(aNodes(0).aRcSimu(j).iSimuNo)
    Next
   
    弹出对话框的内容一次为:
    “数组大小为5”
     “节点1的aRcSimu(0).iSimuNo=11"
     “节点1的aRcSimu(0).iSimuNo=12"
     “节点1的aRcSimu(0).iSimuNo=13"
    符合设想的功能。


To KingSeaMountain():
    感谢回答,不过我的问题不是在传参数的问题,初始化接口已经可以传 自定义的结构以及自定义的结构数组了!
    问题是:这些自定义的结构 一般都需要FindItem,MoveItem(),AddItem之类的函数,如果另外实现某个接口通过分别传这些结构或结构的数组作参数来操作他们,使用起来很不方便和自然。  也就是说:客户端的易使用性和符合习惯是最重要的!
 

    根据上面诸位的回答我想将结构做成对应的接口是最好的办法!这样可以封装这些函数,而且可以隐藏结构具体使用的数据成员!可惜就是性能上损失不少。

原创粉丝点击