none
interop in C# - passing a managed array as ref to ActiveX RRS feed

  • Question

  • Anyone knows much about COM interop in C#?

    I'm having some trouble passing an object as Ref to a COM object.
    If I pass a null object it works fine, but what I want to do is pass a managed array to have it filled by the COM object, so I don't have to 'copy' the whole array into the managed array.

    Maybe I'm taking the problem the wrong way though, so if you know of a way to convert a managed 'object' generated by unmanaged code into a managed array of floats, that would work for me too.
    The goal is to avoid the extra copy I currently have to do

    right now I have to do:

    object dataobj = null
    myactivex.GetValue(param1, param2, ref dataobj)
    System.Array dataarray = (Array)dataobj;
    float[] data = new float[dataarray.Length];

    for (int i=0; i<dataarray.Length;i++)
    {
         data[i] = dataarray.GetValue(i);
    }

    not only the object is already in unmanaged memory, but I have to load it in to an unmanaged object, then copy it again. That means it's really 3 times in memory.
    I want to avoid the memory overhead, and the time overhead to copy the array (with several millions datapoints, it takes several seconds)

    Additional notes:
    The ActiveX is an object that has forms etc... and is loaded in my toolbox.
    I tried using the [Dllimport] to define how the object should be Marshalled but it could not find the function 'getvalue' in the dll, and I don't know it's number. I have no access to the dll code itself, i just have the documentation.

    in the doc, it is defined as:

    long

     

    GetValue(long ID, LPCTSTR pName, VARIANT FAR* pValue)

    where pValue defined as Variant FAR* returns an array of floats (or other things depending on the pName param) but in my case it is always an array of floats

     

     



    Thanks for help!

    Wednesday, April 29, 2009 3:31 PM

Answers

  • A copy is unavoidable, the layout of System.Array and its memory management is fundamentally different from SAFEARRAY.  If this causes a bottleneck, you need to move code from one side of the fence to the other.
    Hans Passant.
    • Marked as answer by Zhi-Xin Ye Tuesday, May 5, 2009 9:55 AM
    Wednesday, April 29, 2009 5:18 PM
    Moderator

All replies

  • Check out this sample at Codeguru http://www.codeguru.com/cpp/com-tech/activex/com/article.php/c2575.

    If you could change the second parameter of "GetValue" to

    SAFEARRAY(

    float)* data

     

    Your life could get much simpler. I hope this helps.

    Wednesday, April 29, 2009 3:44 PM
  • A copy is unavoidable, the layout of System.Array and its memory management is fundamentally different from SAFEARRAY.  If this causes a bottleneck, you need to move code from one side of the fence to the other.
    Hans Passant.
    • Marked as answer by Zhi-Xin Ye Tuesday, May 5, 2009 9:55 AM
    Wednesday, April 29, 2009 5:18 PM
    Moderator
  • Hello,

    Thanks for the reply...
    I guess I'll deal with it right now. I thought that if I could marshall the managed object and 'lock' it in memory, i would be able to pass it as is. Maybe not.

    Anyway, I am having another problem now:
    the code above was to retrieve data: i send a null object and it returns an array.
    Now I use another function that does the reverse and sends an array to the COM object, and I'm getting into another brick wall: it just won't take a filled array as ref param.

    Any idea of how to do this?

    I have:

    data is a filled array of float;

    I tried
    object dataobj = (object)data;
    myActiveX.PutValue(param1, param2, ref dataobj);

    but always get a 'TypeMismatch" error.
    with the documentation still being:

    long PutValue

     

     


    any suggestions on how to pass this array? it does take floats as input, that I know, even though the param is a VARIANT FAR*
    Do I need to copy my whole array into an 'object' again?

    Thanks for help.


    PS: I see in the Marshal Interface that there are ways to 'pin' a managed object and get a handle for it to use with unmanaged code. Yet I can't find a way to pass my array over to the ActiveX.
    Is Marhsalling the way to go, or am I totally off here?


    Friday, May 22, 2009 11:31 PM