Quantcast
Channel: Common Language Runtime Internals and Architecture forum
Viewing all articles
Browse latest Browse all 1710

COM interop: issue with C-style array of interface pointers

$
0
0

Dear community,

I have an issue with COM interop. I need to marshal a C-Style array of interface pointers. I have changed IL to get this array marshaled correctly but I have issues accessing the array elements in the managed code. Below are the IDL as well as my three tries that did not work.

Any suggestions?
Thanks,
dpomt

 

IDL

[local] HRESULT Next([in] ULONG cElems, [out] ISomeObject *prgElems, [out] ULONG *pcFetched); \

        [call_as(Next)] HRESULT RemNext([in] ULONG cElems, [out, size_is(cElems), length_is(*pcFetched)] xxx *prgElems, [out] ULONG *pcFetched); \

 

Generated IL (tlbimp+ildasm)

instance void RemNext([in] uint32 cElems,
              [out] class SomeLib.ISomeObject&  marshal( interface ) prgElems,
              [out] uint32& pcFetched) runtime managed internalcall

 

 

Try #1:
change il to and use then ilasm to recompile:

a) //[in][out] native int& pElemens ==> ref pElements

b) //[out] native int& pElemens ==> out pElements

IntPtr pElements =Marshal.AllocCoTaskMem(iFetchSize * Marshal.SizeOf(typeof(int)));

 

try

{

  while (true)                   

  {

     int iFetchSize = 25;

     int hr = enumBDO.RemNext((uint)iFetchSize,ref pElements, out uiFetched);

     // ^^^ a) ref pElements, b) out pElements

     if (hr < 0)

        Marshal.ThrowExceptionForHR(hr);

                                                                           

     IntPtr pCurrent = pElements; // array!

     for (int i = 0; i < uiFetched; ++i)

     {

        ISomeObject bdoTmp = (ISomeObject)Marshal.GetObjectForIUnknown(pCurrent); 

        //bdoTmp is COMObject but accessing it fails (COMObject is null)

        listBDOs.Add(bdoTmp);

        pCurrent = (IntPtr)((int)pCurrent +Marshal.SizeOf(typeof(int)));

     }

                      

     if (hr ==HRESULTS.S_FALSE)

        break;

  }

}

finally

{

  Marshal.FreeCoTaskMem(pElements);
}

 

è bdoTmp here is a __COMObject, but its content is null

 

 

 

Try #2:
same change of il code as #1 but different code accessing IntPtr
a) //[in][out] native int& pElemens ==> ref pElements

b) //[out] native int& pElemens ==> out pElements

 

IntPtr pElements =Marshal.AllocCoTaskMem(iFetchSize * Marshal.SizeOf(typeof(int)));

 

try

{

  while (true)                   

  {

     int iFetchSize = 25;

     int hr = enumBDO.RemNext((uint)iFetchSize,ref pElements, out uiFetched);

     // ^^^ a) ref pElements, b) out pElements

     if (hr < 0)

        Marshal.ThrowExceptionForHR(hr);

                                                                          

     IntPtr[] managedArray2 = newIntPtr[uiFetched];

     Marshal.Copy(pElements, managedArray2, 0, (int)uiFetched);

     foreach (IntPtr pin managedArray2)

     {

           ISomeObject bdoTmp = (ISomeObject)Marshal.GetObjectForIUnknown(p);
           // ^^^{"Unknown error (Exception from HRESULT: 0x80004005 (E_FAIL))"}

           // System.SystemException {System.Runtime.InteropServices.COMException}

 

           listBDOs.Add(bdoTmp);

       }

       if (hr ==HRESULTS.S_FALSE)

         break;

  }

}

finally

{

  Marshal.FreeCoTaskMem(pElements);
}

 

è Marshal.GetObjectForIUnknown(p); will fail here (see error message on comment above)

 

 

 

Try #3:
same change of il code as #1 but different code accessing IntPtr
a) //[in][out] native int& pElemens ==> ref pElements

b) //[out] native int& pElemens ==> out pElements

 

IntPtr pElements =Marshal.AllocCoTaskMem(iFetchSize * Marshal.SizeOf(typeof(int)));

 

try

{

  while (true)                   

  {

     int iFetchSize = 25;

     int hr = enumBDO.RemNext((uint)iFetchSize,ref pElements, out uiFetched);

     // ^^^ a) ref pElements, b) out pElements

     if (hr < 0)

        Marshal.ThrowExceptionForHR(hr);

                                                                          

        ISomeObject[] bdoArr =newISomeObject [iFetchSize];                                                   

        int hr = enumBDO.RemNext((uint)iFetchSize,ref bdoArr, out uiFetched);// crash here

        if (hr < 0)

           Marshal.ThrowExceptionForHR(hr);

               

        for (int i=0; i<uiFetched; ++i)

        {

           ISomeObject bdoTmp = bdoArr[i];

           listBDOs.Add(bdoTmp);

        }  

     }

}

finally

{

  Marshal.FreeCoTaskMem(pElements);
}

 

è application crashes for call enumBDO.RemNext

         

Any ideas what I am acutally doing wrong?

I read somewhere to use LPARRAY with sizeparam but did not find a possibily to to this in IL.

 


Viewing all articles
Browse latest Browse all 1710

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>