none
How to send C# double array to VC++ ActiveX COM Dll function. RRS feed

  • Question

  • Hi,

    I am using VC++ ActiveX dll in C# windows Application. ActiveX COM dll code is build using Visual C++ 6.0 and I have source code to update.

    I want to create one method in ActiveX dll  accepting double array as an argument and invoking it from C# application.

    I tried creating ActiveX method [GetData(double FAR* dStartPt, long nSize) ]. The corresponding AXInterop Dll in C# application shows

    [GetData(ref double  dStartPt, int nSize) ] signature.

    By this I am able to send a first element as ref, and tried to access other elements of array by  [dStartPt] incrementing (I think this is not right.) but it get only first element right and other zero.

    could you please tell me where I am wrong. OR  information about sending array from C# to ActiveX.

    [I search for SAFEARRAY but could not  add reference to C# project, and Activex Dll is developed long time ago.]

    regards

    sumedh.

    Thursday, November 11, 2010 1:00 PM

Answers

  • Hello sumedh hiwarale,

    1. >> I tried creating ActiveX method [GetData(double FAR* dStartPt, long nSize) ]. The corresponding AXInterop Dll in C# application shows

    >> [GetData(ref double  dStartPt, int nSize) ] signature.

    >> By this I am able to send a first element as ref, and tried to access other elements of array by  [dStartPt] incrementing (I think this is not right.) but it get only first element right and other zero.

    1.1 It is generally not possible to pass a C-style array via COM-Interop even if you have specified the size of the array to be used at runtime (via the size_is() IDL attribute).

    1.2 Hence you are correct in noting that only one element can be sent to the COM GetData() method.

     

    2. In order to achieve a C# signature like the following :

    GetData(double[] dStartPt, int uSize);

    you need to manually modify the interop assembly as follows :

    2.1 Use ildasm to transform the interop assembly into a text file, e.g. ildasm HIRAWALEAX01Lib.dll /out:HIRAWALEAX01Lib.il

    2.2 Then open HIRAWALEAX01Lib.il (a text file) and change the GetData() method signature as follows :

    original :

      .method public hidebysig newslot virtual
              instance void  GetData([in][out] float64& dStartPt,
                                       [in] int32 uSize) runtime managed internalcall

    new :

      .method public hidebysig newslot virtual
              instance void  GetData([in][out] float64[] marshal([+1]) dStartPt,
                                       [in] int32 uSize) runtime managed internalcall

    2.3 That is, we replace the '&' with a '[]' and then indicate that the array size can be found in the parameter at index 1.

    2.4 You then re-create the interop assembly by using the ilasm.exe program, e.g. :

    ilasm /dll HIRAWALEAX01Lib.il

    That is, you re-create the interop assembly (e.g. HIRAWALEAX01Lib.dll) using the newly modified HIRAWALEAX01Lib.il.

     

    3. >> I search for SAFEARRAY but could not  add reference to C# project

    3.1 I'm surprised that you are experiencing difficulties with SAFEARRAY.

    3.2 This is by far the best way to specify arrays in COM-interop.

    3.3 What signature did you use for the COM method (when you tried using SAFEARRAY) ?

     

    - Bio.

     

    Thursday, November 11, 2010 4:51 PM

All replies

  • Hello sumedh hiwarale,

    1. >> I tried creating ActiveX method [GetData(double FAR* dStartPt, long nSize) ]. The corresponding AXInterop Dll in C# application shows

    >> [GetData(ref double  dStartPt, int nSize) ] signature.

    >> By this I am able to send a first element as ref, and tried to access other elements of array by  [dStartPt] incrementing (I think this is not right.) but it get only first element right and other zero.

    1.1 It is generally not possible to pass a C-style array via COM-Interop even if you have specified the size of the array to be used at runtime (via the size_is() IDL attribute).

    1.2 Hence you are correct in noting that only one element can be sent to the COM GetData() method.

     

    2. In order to achieve a C# signature like the following :

    GetData(double[] dStartPt, int uSize);

    you need to manually modify the interop assembly as follows :

    2.1 Use ildasm to transform the interop assembly into a text file, e.g. ildasm HIRAWALEAX01Lib.dll /out:HIRAWALEAX01Lib.il

    2.2 Then open HIRAWALEAX01Lib.il (a text file) and change the GetData() method signature as follows :

    original :

      .method public hidebysig newslot virtual
              instance void  GetData([in][out] float64& dStartPt,
                                       [in] int32 uSize) runtime managed internalcall

    new :

      .method public hidebysig newslot virtual
              instance void  GetData([in][out] float64[] marshal([+1]) dStartPt,
                                       [in] int32 uSize) runtime managed internalcall

    2.3 That is, we replace the '&' with a '[]' and then indicate that the array size can be found in the parameter at index 1.

    2.4 You then re-create the interop assembly by using the ilasm.exe program, e.g. :

    ilasm /dll HIRAWALEAX01Lib.il

    That is, you re-create the interop assembly (e.g. HIRAWALEAX01Lib.dll) using the newly modified HIRAWALEAX01Lib.il.

     

    3. >> I search for SAFEARRAY but could not  add reference to C# project

    3.1 I'm surprised that you are experiencing difficulties with SAFEARRAY.

    3.2 This is by far the best way to specify arrays in COM-interop.

    3.3 What signature did you use for the COM method (when you tried using SAFEARRAY) ?

     

    - Bio.

     

    Thursday, November 11, 2010 4:51 PM
  • Hi Bio,

    [2]

    I managed to update the C# method signature from ref double to double[].

    data send to COM Dll is invalid.

     

    [3]

    Then I tried with SAFEARRAY  and manage to send valid data to COM Dll.

    this is the signature in COM dll

    [GetData(const VARIANT FAR& dStartPt, long nSize) ]

    and this  is in C#.

    [GetData(object dStartPt, int nSize) ]

     

    thanks for your  explaination..

    sumedh hiwarale :-)

    Friday, November 12, 2010 12:36 PM