如何在COM接口中传递IDL基本类型的数组

解决方案 »

  1.   

    传递基本数据类型数组我知道了,使用SafeArray就成了。现在我要使用SAFEARRAY来传递我接口中自定义的结构数组,该如何?
    先贴出部分代码,请大虾帮忙:IDL
    结构:
    struct SessionInfo
    {
        BSTR SesisonID; //ID
        ...
    }
    接口:
    HRESULT GetSessionInfoList([out,retval] SAFEARRAY(struct SessionInfo)* ppSA);在接口实现类中:.h  方法声明STDMETHOD(GetSessionInfoList)(SAFEARRAY ** ppSA);.cpp  方法实现STDMETHODIMP CSessionInterface::GetSessionInfoList(SAFEARRAY ** ppSA)
    {
    AFX_MANAGE_STATE(AfxGetStaticModuleState()); HRESULT hr = S_OK; long idCount = SessionIDToOb.GetCount();
    if(idCount==0) return S_OK;
    BSTR bstr;
    static const NDIMS = 1;
    SAFEARRAY *pSA = NULL;
    SAFEARRAYBOUND dimension[NDIMS];
    dimension[0].lLbound = 0;
    dimension[0].cElements = idCount; pSA = SafeArrayCreate(VT_VOID,NDIMS,dimension);//???类型对不对???
    if(pSA==NULL) return E_FAIL; POSITION pos;
    CString sKey;
    CSession* pSession;
    pos = SessionIDToOb.GetStartPosition();
    long i=0;
    SessionInfo *pSessionInfo = NULL;
    while(pos)
    {
    SessionIDToOb.GetNextAssoc(pos,sKey,(CObject *&)pSession);
    pSessionInfo = new SessionInfo;
    pSessionInfo->SesisonID=pSession->sSessionID.AllocSysString();          //....
    hr = SafeArrayPutElement(pSA,&i,(void *)pSessionInfo);
    i++;
    }
    delete pSessionInfo; if(SUCCEEDED(hr))
    *ppSA = pSA;
    else
    SafeArrayDestroy(pSA);
    return S_OK;
    }哪位有经验的同志给诊断诊断?
      

  2.   

    SAFEARRAY(struct SessionInfo)*
    这个不对,safearray不能直接用于自定义结构
      

  3.   

    可以的,至少编译通过了,而且我也查到了相应文档(《IDL精髓》p.140 电力出版社)说这是可以传递自定义结构的(必须定义在接口中),但没有更细一步的例程,不知有谁用过的,这功能很有用啊!
      

  4.   

    我用MFC做过这种类型的程序,也是传递一个结构安全数组。记得当时MFC做的服务器端程序是outofproc的exe,客户端用vb可以接受结构中的数据,mfc做的客户端就不行了。
    时间过去很长了,记不得具体实现了,代码现在也找不到了。不过似乎我当时创建结构数组时不是用VT_VOID,而是用VT_ARRAY ,即数组中的结构不是指针,而是数据实体。结构也不是new的,而是直接定义。
    你试试
      

  5.   

    用一个带有size_is属性的指针参数传递数组和一个int类型的参数传递数组的大小。
      

  6.   

    struct SessionInfo
    {
        BSTR SesisonID; //ID
        ...
    }
    include "list"
    using namespace std
    list<SessionInfo{> aa;
    用ATL的枚举模板CCollectONSTL ()参数太多我记不住
      

  7.   

    你的safearray创建是一个自定义参数为VT_RECORD  非VT_Void
      

  8.   

    我也有这个问题,用size_is(…)array[],在进程外服务的话只能传一个指针,参数传不回来
    运行不出错,但数据没有完全返回回来
      

  9.   

    //.IDL
    struct SessionInfo
    {
        BSTR SesisonID; //ID
        ...
    }
    struct SessionInfoArray
    {
        long RecordCount;
        SAFEARRAY(struct SessionInfo)  lpSessionInfo;
    }//给每一个结构体加UUID号//.CPP
    hr = LoadRegTypeLib(LIBID_NTVDSOAREPORTCOMLib, 1, 0, GetUserDefaultLCID(), &pTypelib);
    _ASSERT(SUCCEEDED(hr) && pTypelib);
    hr = pTypelib->GetTypeInfoOfGuid(__uuidof(SessionInfo), &pTypeInfo);
    _ASSERT(SUCCEEDED(hr) && pTypeInfo);
    hr = GetRecordInfoFromTypeInfo(pTypeInfo, &pRecInfo);
    _ASSERT(SUCCEEDED(hr) && pRecInfo);psa = SafeArrayCreateVectorEx(VT_RECORD, 0, lpSessionInfoArray.RecordCount, pRecInfo);
    hr = SafeArrayAccessData(psa, (void HUGEP**)&lpSessionInfoArray);//为lpSessionInfoArray->lpSessionInfo->SesisonID赋值SafeArrayUnaccessData(psa);
    lpSessionInfoArray->lpSessionInfo = psa;
      

  10.   

    MSDN上有一个例子,如下。
    我试过,通过(用VB或VC调用),VBSCRIPT不行
    这个例子传入一个long型数组,第二个参数是求和的值。
    另外,我发现,如果组件是进程外的,而要回传数组的话,数组参数类型必须是[in,out]另外 ynlg(ynlg)的方法也是对的。Sample:This sample calculates the sum of long integers in a SAFEARRAY using a function in an ActiveX DLL created with the ActiveX Template Library (ATL) wizard. In Visual C create an ATL DLL using the ATL COM AppWizard. Name it MyAtlDll. 
    From the Insert menu, select New ATL Object. Highlight Objects in the category list and select Simple Object in the Objects list. Click Next. Type in MyClass in the Short Name field, and then click the Attributes tab. Check the following options and then click OK: 
    Threading Model: Apartment
    Interface: Dual
    Aggregation: Yes On the ClassView pane in the workspace, right-click IMyClass and select Add Method. Type AddLongs in the Method Name text box and type the following in the Parameters text box: 
    4.            [in,out] SAFEARRAY (long) *psaMyArray, [in,out] long *plSum Note for Visual C version 6.0: If you are using Visual C version 6.0 you may receive the following error message: Unable to create the function because the header or the implementation file could not be found. This is a known issue in the wizard of Visual C version 6.0. You can by pass this error by manually changing the parameters for the AddLongs method in the header, source and .idl files as explained here: In the Parameters list type in:  [in,out] long *psaMyArray, [in,out] long *plSum On the FileView tab in the workspace, expand MyAtlDll files. Under the header files double-click the MyClass.h header file. At the very end of this file you will find the declaration of your method:  STDMETHOD(AddLongs)(/*[in,out]*/ long *psaMyArray, /*[in,out]*/ long *plSum); Change it to the following:  STDMETHOD(AddLongs)(/*[in,out]*/ SAFEARRAY **psaMyArray, /*[in,out]*/ long *plSum); Under the Source Files list double-click MyClass.cpp. Here you will find the implementation of your method. Change the following line:  STDMETHODIMP CMyClass::AddLongs(long *psaMyArray, long *plSum) to:  STDMETHODIMP CMyClass::AddLongs(SAFEARRAY **psaMyArray, long *plSum) Also, under the Source Files list, double-click the .idl file (the only one with an .idl extension) and locate the following line:  [id(1), helpstring("method AddLongs")] HRESULT AddLongs([in,out] long *psaMyArray, [in,out] long *plSum); Change it to:  [id(1), helpstring("method AddLongs")] HRESULT AddLongs([in,out] SAFEARRAY(long) *psaMyArray, [in,out] long *plSum); Double-click the implementation file, MyClass.cpp, under the Source Files list. In the implementation file add the following code to your function: 
    2.            3.              STDMETHODIMP CMyClass::AddLongs(SAFEARRAY * * psaArray, long * plSum)4.              {5.            6.                 // TODO: Add your implementation code here7.                 long lElements; // number of elements in the array8.                 long iCount;9.                 HRESULT lResult; // return code for OLE functions10.            long *pArrayElements; // pointer to the elements of the array11.       12.            // initializing the output13.            *plSum=0;14.       15.            // checking if it is a one-dimensional array16.            if ( (*psaArray)->cDims != 1 ) return(E_FAIL);17.       18.            // checking if it is an array of longs19.            if ( (*psaArray)->cbElements != 4 ) return(E_FAIL);20.       21.            // how many elements are there in the array22.            lElements=(*psaArray)->rgsabound[0].cElements;23.       24.            // locking the array before using its elements25.            lResult=SafeArrayLock(*psaArray);26.            if(lResult)return(lResult);27.       28.            // using the array29.            pArrayElements=(long*) (*psaArray)->pvData;30.            for (iCount=0; iCount<lElements; iCount++)31.               *plSum = *plSum + pArrayElements[iCount];32.       33.            // releasing the array34.            lResult=SafeArrayUnlock(*psaArray);35.            if (lResult) return(lResult);36.       37.            return S_OK;   } Build the DLL by pressing the F7 key. 
    In Visual Basic, create a new Standard EXE project. Form1 is created by default. 
    Place a command button named Command1 on Form1. 
    Select References from the Project menu and add a reference to the ActiveX DLL created previously (MyAtlDll). 
    Paste the following code into the Click event of Command1: 
    43.       44.         Private Sub Command1_Click()45.            Dim MyObj As New MYATLDLLLib.MyClass46.            Dim ArrayOfLongs(3) As Long47.            Dim lSum As Long48.       49.            ArrayOfLongs(0) = 150.            ArrayOfLongs(1) = 251.            ArrayOfLongs(2) = 352.       53.            MyObj.AddLongs ArrayOfLongs, lSum54.            MsgBox "Result from ATL dll = " & Str$(lSum)   End Sub Press F5 to run your project. 
    Click Command1. You should see a message box that displays the value 6 returned from the AddLongs method.