none
Passing Byte Array from C# to Activex Control RRS feed

  • Question

  • Hi,    
        I want to pass a byte array from C# to activex control, I am not sure how can I do that? 
        I tried out follwing things but they didn't work :
        1) My activex method had a singature like method(byte * obj). For this in C# I got the signature which looks like method(ref byte obj).  Now if I try to pass an byte array here it give me an error(which is very well understood).

        2) My activex method had a signature like method(byte ** obj). For this in C# I got the signature which looks like method(IntPtr obj). now here I tried to convert byte array to IntPtr but it also gave me error.

        3) My activex method had a signature like method(VARIANT * obj). For this C# representation was method(void * obj) but when I typecasted by byte array to void and tryied to pass it here it also gave me error.

        I really don't have any idea what exactly is going wrong and where in all above method. Can somebody tell me how can I achieve this?  I also want to pass another byte array from activex to C#. And I am not sure how I will achive that as well.
    So honestly speaking I want some way by which I can pass byte array from C# to activex and also other way round. And both of them will be seperate, i.e. One will be a method call from C# to activex  and another will be event from activex to c#.

    I tried to search a lot but looks like ther are not many people who tried this thing and if some of them have tired they haven't posted a nice and compelte solution to the problem.

    So please any help will be greatly appriciated. If you could provide a simple code snippet for C# and C++(activex method signature ) that will be helpful. Sample signature will help me a lot.
     
    Saurabh Surana
    Tuesday, October 7, 2008 2:10 PM

All replies

  • 1) The ActiveX (COM) method needs to be something like mehod([length_is(nCount)] byte *pByteArray, int nCount) so that COM knows the length of the byte array when it needs to marshal data across apartment bounaries. You might get away without the length_is stuff if you are not calling through a proxy pointer. In C#, you can use method([MarshalAs(UnmanagedType.LpArray, SizeParamIndex=1] byte[] byteArray, int size). If you are passing the array from C# to the ActiveX control, the SizeParamIndex is not absolutely necessary (because CLR knows about the size of the managed byte array), but certainly is nice to have. Please refer to http://msdn.microsoft.com/en-us/library/z6cfh6e6(VS.71).aspx for more details.

    2) Passing an C Array by reference is not well supported at this moment. You might want to use SAFEARRAY instead. Using IntPtr and marshal by yourself works too but you need to write some extra code.

    3) In C#, it should be method(ref object obj). Depending on whether it is [in], [out], or [in, out], you need to use [in]ref object, out object,
    or ref object, respectively.


    Tuesday, October 7, 2008 2:52 PM
    Moderator
  • Hi Yi Zhang,
    Thanks for your reply.

    With approach 1 we have changed activex code as you suggested. Now the method signature looks like
    MyClass::method([size_is[nCount] byte * pByteArray,int nCount) (I got some errors while suing lenght_is so I used size_is parameter.)

    Now when I try to use this in C#, I create an object of MyClass in C# and try to call the method but I am not able to understand how to use MarshalAs(UnmanagedType.LpArray, SizeParamIndex=1] while calling the method on that object it gives me an error. I guess its only possible to use MarshalAs parameter while declaring the method, is there any other way to redeclare activex class method in C# for marshaling.

    Of course I don't' want to use PInvoke since I have created a activex Control.

     


    Saurabh Surana
    Wednesday, October 8, 2008 6:32 AM
  • OLE automation rules requires you to use a SAFEARRAY for the ActiveX method argument.
    Hans Passant.
    Wednesday, October 8, 2008 11:39 AM
    Moderator

  •     Is there a way to redeclare a activex method signature in C# where I can specify attributes "MarshalAs(UnmanagedType.LpArray, SizeParamIndex=1]". Because I am sure I cannot specify them at the time calling the method on object. Then how can I achieve this?

    If somebody could provide me a sample code here then that will be very much helpful.



    Saurabh Surana
    Wednesday, October 8, 2008 3:07 PM
  • If you cannot change the signature of the ActiveX control method, and you use something like AxImp.exe to convert the type library of the ActiveX control to a WinForm control, it is not directly supported, because the array information is lost (except for constant length arrays) in the type library. You can only disassemble the generated WinForm control dll into IL code using ILDASM.exe, change the method signature, and then compile it into DLL using ILASM.exe.

    If you can control the method signature of your ActiveX control, the best option is to use SafeArray, which is self-described, and OLE automation compatible.

    This posting is provided "AS IS" with no warranties, and confers no rights.
    Thursday, October 9, 2008 5:51 AM
    Moderator
  • Hi Yi Zhang,
    I tried following things.
    1) Changed my activex control function defination as void test2(SAFEARRAY(BYTE)* testParam)
    2) When I tried to use this method in C# the intellisence showd me the signature as "ref System.Array testParam". Hence I tried following :

    byte[] tmpArray = new byte[10];

    for (int i = 0; i < 10; i++) { tmpArray[i] = (byte)i; }

    Array ar = tmpArray;

    myactivexControl.test2(ref ar);

    3) Everything got compiled properly but while executing I got runtime COM exception saying Parameter mismatch.
    Am I missing anything here?


    Saurabh Surana
    Thursday, October 9, 2008 6:21 AM