none
how to make a fixedlength and static array?

    Question

  • I was wondering how to create an safe array out of the following code which has a fixed length and static array:

      Dim x(40), y(40) As Integer
        Private Structure InputReport
            <MarshalAsAttribute(UnmanagedType.SafeArray, SafeArraySubType:=VarEnum.VT_VARIANT)> Dim InputReport1() As Object
            Dim InputReportMain As System.Array
        End Structure
    Public Function sendinputreport(xcoord As Integer, ycoord As Integer, leftclick As Boolean, rightclick As Boolean) As Boolean
            'device report to send to computer (x,y coordinates, left or right clicks, and scrolling).
            'file contents:
            'number of devices
            'x for dev1
            'y for dev1
            'left click for dev1
            'x for dev2
            'y for dev2
            'left click for dev2
            Dim mousereport As InputReport
            mousereport.InputReport1 = New Object(5) {CByte(0), CByte(x(usernum)), CByte(y(usernum)), CByte(0), CByte(0), CByte(0)}
         
            x(usernum) = xcoord
            y(usernum) = ycoord
            MsgBox(x(usernum))
            mousereport.InputReportMain = Array.CreateInstance(GetType(Byte), 5)
            mousereport.InputReportMain = mousereport.InputReport1
            'InputReport1(0) = CByte(0)
            'InputReport1(1) = CByte(x(usernum))
            'InputReport1(2) = CByte(y(usernum))
            'InputReport1(3) = CByte(0)
            'InputReport1(4) = CByte(0)
    
            'make sure byte is below 255 because thats the max it can be in integer or other format.
            If x(usernum) <= 255 And y(usernum) <= 255 Then
                'InputReportMain.SetValue(CByte(0), 0)
                'InputReportMain.SetValue(CByte(100), 1)
                'InputReportMain.SetValue(CByte(100), 2)
                'InputReportMain.SetValue(CByte(0), 3)
                'InputReportMain.SetValue(CByte(0), 4)
                'GenericHIDDev(usernum).devInputReportBytes(InputReport1)
                GenericHIDDev(usernum).QueueInputReport(mousereport.InputReportMain, 0)
                GenericHIDDev(usernum).StartProcessing()
            End If
    
            sendinputreport = True
        End Function

    I know this seems weird but I was trying to call a com object but visual studio automatically create a RCW(runtime callable wrapper) that wrappers the com code and turns the safe array to type system.array. I thing because the attributes fixed and static are not being passed to com the unmanaged code excludes the data from being used.


    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr




    • Edited by The Thinker Monday, July 15, 2013 7:39 PM edit4
    Monday, July 15, 2013 7:07 PM

Answers

  • I cannot try the code, I only can read and try to understand

    If I understand it right, 

      1) you create/get the data from a VB assembly

      2) you then pass this data to a C++ assembly (To this point, no problem, the data marshals)

      3) then you pass the data to a driver (An it is there that it crash, the driver don't like the structure of the data you are passing)

    --------------

     If this is right, and also if from VBScript you can get it to work, I have to conclude that on the C++ side, you are able to create an array/structure that is acceptable by the driver.

    Then Have you try to create a new array in C++ and just recopy the data recieved from VB to it? And then pass this new copy to the driver. This way, the data will be to an acceptable form for the driver.

    It does not bluescreen me the driver just does not see those parameters so it does nothing with the data (I have a messagebox on c++ side telling me if the data passed correctly and safe array type/parameters). But vbscript passes those parameters and it lets them through. This is from microsofts dsf(device simulation framework) libraries but I need softhidreceiver.dll which is unmanaged. It is a c/c++ com dll but Iam not for sure how I would hybrid it out. 

    For #1 and #2 yes that is correct except for the parameters to the function.  I have not tried passing my system.array variable above as a pointer to the c++ function though so I do not know fully if it will work from vb.net yet or not. If I knew how to convert the c/c++ unmanaged com code to dotnet dll I would do it but that would probably require some time recoding everything as it has some custom code in spots I noticed on the c++ side that might not convert at all.

    Is it true that in c# you can  declare pointers similar to c++ such as: byte[] *myptr; <- this is close to the equilivent Iam looking for in vb.net except its in c#.


    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr





    If you look on my kinect multipoint page here: http://kinectmultipoint.codeplex.com you should be able to play around with the c++ dll i was talking about and the full vb.net source. You just need the dsf runtime from the wdk (not the code parts just the runtime which contains dlls and system files and services) and the dlls in the bin folder of the dsf mouse wrapper library vb.net version on the downloads section. I can upload the part I have done now but its not much change except for the structure is their instead of declaring the system.array locally in the sendinputreport function. Hope that would help some. I would hate to convert it in c++ because of the possibility their are no ways to get some functions or subs in c++ to show to dotnet.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr


    Nevermind, I set the flags above on the c++ side and it did not help at all. I think it might be the way the data is being interoped to c++ from the managed side. I'll just start a new thread with my information from the common language runtime forum I tried to get an answer on.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr

    • Marked as answer by The Thinker Thursday, July 18, 2013 5:50 PM
    Thursday, July 18, 2013 5:50 PM

All replies

  • I was wondering how to create an safe array out of the following code which has a fixed length and static array:

      Dim x(40), y(40) As Integer
        Private Structure InputReport
            <MarshalAsAttribute(UnmanagedType.SafeArray, SafeArraySubType:=VarEnum.VT_VARIANT)> Dim InputReport1() As Object
            Dim InputReportMain As System.Array
        End Structure
    Public Function sendinputreport(xcoord As Integer, ycoord As Integer, leftclick As Boolean, rightclick As Boolean) As Boolean
            'device report to send to computer (x,y coordinates, left or right clicks, and scrolling).
            'file contents:
            'number of devices
            'x for dev1
            'y for dev1
            'left click for dev1
            'x for dev2
            'y for dev2
            'left click for dev2
            Dim mousereport As InputReport
            mousereport.InputReport1 = New Object(5) {CByte(0), CByte(x(usernum)), CByte(y(usernum)), CByte(0), CByte(0), CByte(0)}
         
            x(usernum) = xcoord
            y(usernum) = ycoord
            MsgBox(x(usernum))
            mousereport.InputReportMain = Array.CreateInstance(GetType(Byte), 5)
            mousereport.InputReportMain = mousereport.InputReport1
            'InputReport1(0) = CByte(0)
            'InputReport1(1) = CByte(x(usernum))
            'InputReport1(2) = CByte(y(usernum))
            'InputReport1(3) = CByte(0)
            'InputReport1(4) = CByte(0)
    
            'make sure byte is below 255 because thats the max it can be in integer or other format.
            If x(usernum) <= 255 And y(usernum) <= 255 Then
                'InputReportMain.SetValue(CByte(0), 0)
                'InputReportMain.SetValue(CByte(100), 1)
                'InputReportMain.SetValue(CByte(100), 2)
                'InputReportMain.SetValue(CByte(0), 3)
                'InputReportMain.SetValue(CByte(0), 4)
                'GenericHIDDev(usernum).devInputReportBytes(InputReport1)
                GenericHIDDev(usernum).QueueInputReport(mousereport.InputReportMain, 0)
                GenericHIDDev(usernum).StartProcessing()
            End If
    
            sendinputreport = True
        End Function

    I know this seems weird but I was trying to call a com object but visual studio automatically create a RCW(runtime callable wrapper) that wrappers the com code and turns the safe array to type system.array. I thing because the attributes fixed and static are not being passed to com the unmanaged code excludes the data from being used.


    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr



    For reference this is for my multi-mouse emulator Iam creating but if I can figure out this one problem I can limit the non-working part to c++ code side (if it continues to not work). I will write a nice article on msdn (I think they call them technet articles right now though) about it so anyone can change it to their own device later. But Iam trying to make the process simple as can be.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr


    • Edited by The Thinker Monday, July 15, 2013 7:32 PM edit 4
    Monday, July 15, 2013 7:32 PM
  • Since you are writing the code on both side, managed and unmanaged,

    Why dont you just use in VB a regular array  and pass to the c++ function the lenght of the array and a pointer to the array?

    It is much simpler to handle on both side (Make sure that the VB array dont get out of scope, so it dont get garbaged collected while the C++ method is using it)

    (I like to use StdCall for that)

        <Runtime.InteropServices.DllImport("API Path", SetLastError:=True, CallingConvention:=CallingConvention.StdCall)> _
        Private Shared Sub Whatever(ByVal Length As Integer, <MarshalAs(UnmanagedType.LPArray)> ByVal MyArray() As Integer)
        End Function


    • Edited by Crazypennie Monday, July 15, 2013 9:21 PM 132465
    Monday, July 15, 2013 9:17 PM
  • Since you are writing the code on both side, managed and unmanaged,

    Why dont you just use in VB a regular array  and pass to the c++ function the lenght of the array and a pointer to the array?

    It is much simpler to handle on both side (Make sure that the VB array dont get out of scope, so it dont get garbaged collected while the C++ method is using it)

    (I like to use StdCall for that)

        <Runtime.InteropServices.DllImport("API Path", SetLastError:=True, CallingConvention:=CallingConvention.StdCall)> _
        Private Shared Sub Whatever(ByVal Length As Integer, <MarshalAs(UnmanagedType.LPArray)> ByVal MyArray() As Integer)
        End Function



    Because I need to specify the device number its equilivent to sending an inputreport to nothing or sending device input in thin air (Crash it would be. :{ ). The usernum is really the device num just change them out in this instance they are the same. Note: I just tested the vbscript array code which is very similar on the c++ side and it works and returns the exact array format too as the current vb.net code except the array does not have the static and fixed length parameters. Thats weird though. :/

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr



    • Edited by The Thinker Monday, July 15, 2013 10:25 PM edit 4
    Monday, July 15, 2013 10:24 PM
  • Since you are writing the code on both side, managed and unmanaged,

    Why dont you just use in VB a regular array  and pass to the c++ function the lenght of the array and a pointer to the array?

    It is much simpler to handle on both side (Make sure that the VB array dont get out of scope, so it dont get garbaged collected while the C++ method is using it)

    (I like to use StdCall for that)

        <Runtime.InteropServices.DllImport("API Path", SetLastError:=True, CallingConvention:=CallingConvention.StdCall)> _
        Private Shared Sub Whatever(ByVal Length As Integer, <MarshalAs(UnmanagedType.LPArray)> ByVal MyArray() As Integer)
        End Function



    Because I need to specify the device number its equilivent to sending an inputreport to nothing or sending device input in thin air (Crash it would be. :{ ). The usernum is really the device num just change them out in this instance they are the same. Note: I just tested the vbscript array code which is very similar on the c++ side and it works and returns the exact array format too as the current vb.net code except the array does not have the static and fixed length parameters. Thats weird though. :/

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr




    found the library in dotnet that has what Iam looking for but the dotnet library is not found in visual studio? http://msdn.microsoft.com/en-us/library/vstudio/microsoft.visualstudio.ole.interop.safearray.ffeatures(v=vs.100).aspx

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr

    Tuesday, July 16, 2013 8:58 PM
  • Since you are writing the code on both side, managed and unmanaged,

    Why dont you just use in VB a regular array  and pass to the c++ function the lenght of the array and a pointer to the array?

    It is much simpler to handle on both side (Make sure that the VB array dont get out of scope, so it dont get garbaged collected while the C++ method is using it)

    (I like to use StdCall for that)

        <Runtime.InteropServices.DllImport("API Path", SetLastError:=True, CallingConvention:=CallingConvention.StdCall)> _
        Private Shared Sub Whatever(ByVal Length As Integer, <MarshalAs(UnmanagedType.LPArray)> ByVal MyArray() As Integer)
        End Function



    Because I need to specify the device number its equilivent to sending an inputreport to nothing or sending device input in thin air (Crash it would be. :{ ). The usernum is really the device num just change them out in this instance they are the same. Note: I just tested the vbscript array code which is very similar on the c++ side and it works and returns the exact array format too as the current vb.net code except the array does not have the static and fixed length parameters. Thats weird though. :/

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr




    found the library in dotnet that has what Iam looking for but the dotnet library is not found in visual studio? http://msdn.microsoft.com/en-us/library/vstudio/microsoft.visualstudio.ole.interop.safearray.ffeatures(v=vs.100).aspx

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr


    nevermind i found the library time to do some playing around it appears its already in the GAC I just have to reference it. Edit: I want to try and get it working from dotnet redistributables if possible since that dll cannot be redistributed or at least I think it cannot.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr




    Thats weird its just a structure. I need the equilivent passed to c++ with fFeatures which are flags defining the safe array but Iam trying to figure out how to do that. Edit: tried to use marshalas sizeconst field but visual studio complained about it not being able to be used on the safe array type.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr



    • Edited by The Thinker Tuesday, July 16, 2013 9:28 PM edit 5
    Tuesday, July 16, 2013 9:26 PM
  • Since you are writing the code on both side, managed and unmanaged,

    Why dont you just use in VB a regular array  and pass to the c++ function the lenght of the array and a pointer to the array?

    It is much simpler to handle on both side (Make sure that the VB array dont get out of scope, so it dont get garbaged collected while the C++ method is using it)

    (I like to use StdCall for that)

        <Runtime.InteropServices.DllImport("API Path", SetLastError:=True, CallingConvention:=CallingConvention.StdCall)> _
        Private Shared Sub Whatever(ByVal Length As Integer, <MarshalAs(UnmanagedType.LPArray)> ByVal MyArray() As Integer)
        End Function



    Because I need to specify the device number its equilivent to sending an inputreport to nothing or sending device input in thin air (Crash it would be. :{ ). The usernum is really the device num just change them out in this instance they are the same. Note: I just tested the vbscript array code which is very similar on the c++ side and it works and returns the exact array format too as the current vb.net code except the array does not have the static and fixed length parameters. Thats weird though. :/

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr




    found the library in dotnet that has what Iam looking for but the dotnet library is not found in visual studio? http://msdn.microsoft.com/en-us/library/vstudio/microsoft.visualstudio.ole.interop.safearray.ffeatures(v=vs.100).aspx

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr


    nevermind i found the library time to do some playing around it appears its already in the GAC I just have to reference it. Edit: I want to try and get it working from dotnet redistributables if possible since that dll cannot be redistributed or at least I think it cannot.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr




    Thats weird its just a structure. I need the equilivent passed to c++ with fFeatures which are flags defining the safe array but Iam trying to figure out how to do that. Edit: tried to use marshalas sizeconst field but visual studio complained about it not being able to be used on the safe array type.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr




    CrazyPennie can marshalas pass attributes for an array to com? or pinvoke an  method on an already created instance of an object?

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr



    • Edited by The Thinker Tuesday, July 16, 2013 9:40 PM edit 6
    Tuesday, July 16, 2013 9:35 PM
  • You are marshalling the complete structure, not just the array?

    Try this then, "ByValArray"

    <StructLayout(LayoutKind.Sequential)>
    Public Structure SomeStruct
        <MarshalAs(UnmanagedType.ByValArray, SizeConst:=40)> Public someArray() As Integer
    End Structure


    and

        <Runtime.InteropServices.DllImport("API Path", SetLastError:=True, CallingConvention:=CallingConvention.StdCall)> _
        Private Shared Sub Whatever( ByVal Struct As SomeStruct)
        End Function

    Would match This

    struct SomeStruct {
        int someArray[40];
    }

    In C++ use Extern C
    • Edited by Crazypennie Wednesday, July 17, 2013 9:33 AM 213546
    Wednesday, July 17, 2013 9:11 AM
  • Another way,

      Your C++ DLL, You can make it mixed code, managed and unmanaged  

      Create a mixed code DLL then you  Just need to use "Pragma Managed" or "Pragma Unmanaged" in front of your method to make it managed or not. (Check the exact spelling ... )

    Then marschaling C++ managed to C++ unmanaged inside a single assembly is easier

    Inside the mixed C++ assembly, managed and unmanaged method can call each other ( still need to marshal, but it is easier)

    So, from the example in my previous path, the mathod "Whatever" can be managed and you can call it just like any method. This method can then call an unmanaged method to execute what need to be done by unmanaged code

    You may also just need to add a reference to the DLL just like if it was a regular VB DLL

     --- This is a good way to go if you know that the DLL will always only be called from managed code. 


    ------------------

    This if the way used by the .NET Framework. this is why you can simply add a reference to any Framework DLL, call the managed method inside it, and internally, some unmanaged method are called when needed


    • Edited by Crazypennie Wednesday, July 17, 2013 10:05 AM 321546
    Wednesday, July 17, 2013 9:48 AM
  • Another way,

      Your C++ DLL, You can make it mixed code, managed and unmanaged  

      Create a mixed code DLL then you  Just need to use "Pragma Managed" or "Pragma Unmanaged" in front of your method to make it managed or not. (Check the exact spelling ... )

    Then marschaling C++ managed to C++ unmanaged inside a single assembly is easier

    Inside the mixed C++ assembly, managed and unmanaged method can call each other ( still need to marshal, but it is easier)

    So, from the example in my previous path, the mathod "Whatever" can be managed and you can call it just like any method. This method can then call an unmanaged method to execute what need to be done by unmanaged code

    You may also just need to add a reference to the DLL just like if it was a regular VB DLL

     --- This is a good way to go if you know that the DLL will always only be called from managed code. 


    ------------------

    This if the way used by the .NET Framework. this is why you can simply add a reference to any Framework DLL, call the managed method inside it, and internally, some unmanaged method are called when needed


    Its funny though because it passes the internal data correctly above with the structure or without it but the variables defined still. For instance, I get the values 0,100,100,0,0,0 but the format of the safe array is different.  But I know the vbscript that did the same thing just has an object type or similar passing the same values and works. For easier reference, Iam trying to pass a byte type safe array from vb.net to c++ but the values are correct on the c++ side but because it does not like the format of the data passed the driver code fails to accept the values. Edit: I know the underlying c++ code wants the safe array data to be of type byte. vbscript code is as simple as this:

    Dim InputReport1(4) InputReport1(0) = 0 InputReport1(1) = 100 'x coordinates of mouse InputReport1(2) = 100 'y coordinates of mouse InputReport1(3) = 0 InputReport1(4) = 0

    GenericHIDDev(usernum).QueueInputReport(InputReport1, 0)
                GenericHIDDev
    (usernum).StartProcessing()



    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr




    • Edited by The Thinker Wednesday, July 17, 2013 5:43 PM edit 4
    Wednesday, July 17, 2013 5:28 PM
  • Another way,

      Your C++ DLL, You can make it mixed code, managed and unmanaged  

      Create a mixed code DLL then you  Just need to use "Pragma Managed" or "Pragma Unmanaged" in front of your method to make it managed or not. (Check the exact spelling ... )

    Then marschaling C++ managed to C++ unmanaged inside a single assembly is easier

    Inside the mixed C++ assembly, managed and unmanaged method can call each other ( still need to marshal, but it is easier)

    So, from the example in my previous path, the mathod "Whatever" can be managed and you can call it just like any method. This method can then call an unmanaged method to execute what need to be done by unmanaged code

    You may also just need to add a reference to the DLL just like if it was a regular VB DLL

     --- This is a good way to go if you know that the DLL will always only be called from managed code. 


    ------------------

    This if the way used by the .NET Framework. this is why you can simply add a reference to any Framework DLL, call the managed method inside it, and internally, some unmanaged method are called when needed


    Its funny though because it passes the internal data correctly above with the structure or without it but the variables defined still. For instance, I get the values 0,100,100,0,0,0 but the format of the safe array is different.  But I know the vbscript that did the same thing just has an object type or similar passing the same values and works. For easier reference, Iam trying to pass a byte type safe array from vb.net to c++ but the values are correct on the c++ side but because it does not like the format of the data passed the driver code fails to accept the values. Edit: I know the underlying c++ code wants the safe array data to be of type byte. vbscript code is as simple as this:

    Dim InputReport1(4) InputReport1(0) = 0 InputReport1(1) = 100 'x coordinates of mouse InputReport1(2) = 100 'y coordinates of mouse InputReport1(3) = 0 InputReport1(4) = 0

    GenericHIDDev(usernum).QueueInputReport(InputReport1, 0)
                GenericHIDDev(usernum).StartProcessing()



    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr




    Heres the c++ idl file signature which is: SAFEARRAY(VARIANT). The queueinputreport looks like this in c++:

    STDMETHODIMP CHIDDevice::QueueInputReport( SAFEARRAY* psaInputReport, UINT timeoutDuration )
    /*++
    Routine Description:
       Queues additional input reports
    
    Arguments:
        IdleTimeout - used to set the value of the log level
    
    Return value:
        S_OK
    --*/
    {
        VARIANT HUGEP*      pArrayData  = NULL;
        ULONG               cbData      = 0;
        LONG                lLBound     = 0;
        LONG                lUBound     = 0;
        HRESULT             hr          = S_OK;
        HID_INPUT_REPORT    inputReport;
        BOOLEAN             result      = TRUE;
    
        // Initialize Structure
        inputReport.timeout = timeoutDuration;
        inputReport.cbInputReport = 0;
        inputReport.pbInputReport = NULL;
    
        // Get SAFEARRAY size
        IfFailHrGo(SafeArrayGetLBound(psaInputReport, 1, &lLBound));
        IfFailHrGo(SafeArrayGetUBound(psaInputReport, 1, &lUBound));
        IfFalseHrGo(lUBound > lLBound, E_UNEXPECTED);
        cbData = lUBound - lLBound + 1;
    
        inputReport.pbInputReport = (BYTE*)CoTaskMemAlloc( cbData * sizeof(BYTE) );
         _TCHAR szBuffer3[100];
        _stprintf_s(szBuffer3, _T("%i"), psaInputReport->fFeatures);
      	MessageBox(NULL,L"array content",szBuffer3,NULL);
        // If the memory Allocation fails, then fail and exit
        if( inputReport.pbInputReport == NULL )
        {
            hr = E_UNEXPECTED;
            goto Exit;
        }
        
        IfFailHrGo( SafeArrayAccessData( psaInputReport, 
                                         (void HUGEP**)&pArrayData ) );
    
        // Step through the SAFEARRAY and populating only BYTE input report
        // and bail out if the type is not correct
        for( LONG i = lLBound; i <= lUBound; ++i )
        {
            if (pArrayData[i].vt == VT_UI1)
            {
    			 _TCHAR szBuffer[100];
        _stprintf_s(szBuffer, _T("%i"), pArrayData[i].bVal);
      	MessageBox(NULL,L"array content",szBuffer,NULL);	
                inputReport.pbInputReport[i-lLBound] = pArrayData[i].bVal;
    			 _TCHAR szBuffer2[100];
        _stprintf_s(szBuffer2, _T("%i"), inputReport.pbInputReport[i]);
      	MessageBox(NULL,L"input report array content",szBuffer,NULL);
            }
            else
            {
                hr = E_FAIL;
    
                goto Exit;
            }
        }
        
        inputReport.cbInputReport = cbData;
        
        // Add the report to the input queue (does a shallow copy so no need to free the array data)
        result = m_InputReportQueue.insert( inputReport );
        if (result == FALSE)
        {
            hr = E_FAIL;
        }
    
    Exit:
        SafeArrayUnaccessData(psaInputReport);
        if( FAILED(hr) )
        {
            CoTaskMemFree(inputReport.pbInputReport);
        }
        return hr;
    }


    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr

    Wednesday, July 17, 2013 5:48 PM
  • Another way,

      Your C++ DLL, You can make it mixed code, managed and unmanaged  

      Create a mixed code DLL then you  Just need to use "Pragma Managed" or "Pragma Unmanaged" in front of your method to make it managed or not. (Check the exact spelling ... )

    Then marschaling C++ managed to C++ unmanaged inside a single assembly is easier

    Inside the mixed C++ assembly, managed and unmanaged method can call each other ( still need to marshal, but it is easier)

    So, from the example in my previous path, the mathod "Whatever" can be managed and you can call it just like any method. This method can then call an unmanaged method to execute what need to be done by unmanaged code

    You may also just need to add a reference to the DLL just like if it was a regular VB DLL

     --- This is a good way to go if you know that the DLL will always only be called from managed code. 


    ------------------

    This if the way used by the .NET Framework. this is why you can simply add a reference to any Framework DLL, call the managed method inside it, and internally, some unmanaged method are called when needed


    Its funny though because it passes the internal data correctly above with the structure or without it but the variables defined still. For instance, I get the values 0,100,100,0,0,0 but the format of the safe array is different.  But I know the vbscript that did the same thing just has an object type or similar passing the same values and works. For easier reference, Iam trying to pass a byte type safe array from vb.net to c++ but the values are correct on the c++ side but because it does not like the format of the data passed the driver code fails to accept the values. Edit: I know the underlying c++ code wants the safe array data to be of type byte. vbscript code is as simple as this:

    Dim InputReport1(4) InputReport1(0) = 0 InputReport1(1) = 100 'x coordinates of mouse InputReport1(2) = 100 'y coordinates of mouse InputReport1(3) = 0 InputReport1(4) = 0

    GenericHIDDev(usernum).QueueInputReport(InputReport1, 0)
                GenericHIDDev(usernum).StartProcessing()



    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr




    Heres the c++ idl file signature which is: SAFEARRAY(VARIANT). The queueinputreport looks like this in c++:

    STDMETHODIMP CHIDDevice::QueueInputReport( SAFEARRAY* psaInputReport, UINT timeoutDuration )
    /*++
    Routine Description:
       Queues additional input reports
    
    Arguments:
        IdleTimeout - used to set the value of the log level
    
    Return value:
        S_OK
    --*/
    {
        VARIANT HUGEP*      pArrayData  = NULL;
        ULONG               cbData      = 0;
        LONG                lLBound     = 0;
        LONG                lUBound     = 0;
        HRESULT             hr          = S_OK;
        HID_INPUT_REPORT    inputReport;
        BOOLEAN             result      = TRUE;
    
        // Initialize Structure
        inputReport.timeout = timeoutDuration;
        inputReport.cbInputReport = 0;
        inputReport.pbInputReport = NULL;
    
        // Get SAFEARRAY size
        IfFailHrGo(SafeArrayGetLBound(psaInputReport, 1, &lLBound));
        IfFailHrGo(SafeArrayGetUBound(psaInputReport, 1, &lUBound));
        IfFalseHrGo(lUBound > lLBound, E_UNEXPECTED);
        cbData = lUBound - lLBound + 1;
    
        inputReport.pbInputReport = (BYTE*)CoTaskMemAlloc( cbData * sizeof(BYTE) );
         _TCHAR szBuffer3[100];
        _stprintf_s(szBuffer3, _T("%i"), psaInputReport->fFeatures);
      	MessageBox(NULL,L"array content",szBuffer3,NULL);
        // If the memory Allocation fails, then fail and exit
        if( inputReport.pbInputReport == NULL )
        {
            hr = E_UNEXPECTED;
            goto Exit;
        }
        
        IfFailHrGo( SafeArrayAccessData( psaInputReport, 
                                         (void HUGEP**)&pArrayData ) );
    
        // Step through the SAFEARRAY and populating only BYTE input report
        // and bail out if the type is not correct
        for( LONG i = lLBound; i <= lUBound; ++i )
        {
            if (pArrayData[i].vt == VT_UI1)
            {
    			 _TCHAR szBuffer[100];
        _stprintf_s(szBuffer, _T("%i"), pArrayData[i].bVal);
      	MessageBox(NULL,L"array content",szBuffer,NULL);	
                inputReport.pbInputReport[i-lLBound] = pArrayData[i].bVal;
    			 _TCHAR szBuffer2[100];
        _stprintf_s(szBuffer2, _T("%i"), inputReport.pbInputReport[i]);
      	MessageBox(NULL,L"input report array content",szBuffer,NULL);
            }
            else
            {
                hr = E_FAIL;
    
                goto Exit;
            }
        }
        
        inputReport.cbInputReport = cbData;
        
        // Add the report to the input queue (does a shallow copy so no need to free the array data)
        result = m_InputReportQueue.insert( inputReport );
        if (result == FALSE)
        {
            hr = E_FAIL;
        }
    
    Exit:
        SafeArrayUnaccessData(psaInputReport);
        if( FAILED(hr) )
        {
            CoTaskMemFree(inputReport.pbInputReport);
        }
        return hr;
    }


    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr


    Anyone good with byte pointers from dotnet to unmanaged code? I think I just realized I should try a point to inputreport1 or inputreportmain. *facepalm*

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr



    • Edited by The Thinker Wednesday, July 17, 2013 7:08 PM edit 5
    Wednesday, July 17, 2013 7:05 PM
  • I cannot try the code, I only can read and try to understand

    If I understand it right, 

      1) you create/get the data from a VB assembly

      2) you then pass this data to a C++ assembly (To this point, no problem, the data marshals)

      3) then you pass the data to a driver (An it is there that it crash, the driver don't like the structure of the data you are passing)

    --------------

     If this is right, and also if from VBScript you can get it to work, I have to conclude that on the C++ side, you are able to create an array/structure that is acceptable by the driver.

    Then Have you try to create a new array in C++ and just recopy the data recieved from VB to it? And then pass this new copy to the driver. This way, the data will be to an acceptable form for the driver.

    Wednesday, July 17, 2013 9:35 PM
  • I cannot try the code, I only can read and try to understand

    If I understand it right, 

      1) you create/get the data from a VB assembly

      2) you then pass this data to a C++ assembly (To this point, no problem, the data marshals)

      3) then you pass the data to a driver (An it is there that it crash, the driver don't like the structure of the data you are passing)

    --------------

     If this is right, and also if from VBScript you can get it to work, I have to conclude that on the C++ side, you are able to create an array/structure that is acceptable by the driver.

    Then Have you try to create a new array in C++ and just recopy the data recieved from VB to it? And then pass this new copy to the driver. This way, the data will be to an acceptable form for the driver.

    It does not bluescreen me the driver just does not see those parameters so it does nothing with the data (I have a messagebox on c++ side telling me if the data passed correctly and safe array type/parameters). But vbscript passes those parameters and it lets them through. This is from microsofts dsf(device simulation framework) libraries but I need softhidreceiver.dll which is unmanaged. It is a c/c++ com dll but Iam not for sure how I would hybrid it out. 

    For #1 and #2 yes that is correct except for the parameters to the function.  I have not tried passing my system.array variable above as a pointer to the c++ function though so I do not know fully if it will work from vb.net yet or not. If I knew how to convert the c/c++ unmanaged com code to dotnet dll I would do it but that would probably require some time recoding everything as it has some custom code in spots I noticed on the c++ side that might not convert at all.

    Is it true that in c# you can  declare pointers similar to c++ such as: byte[] *myptr; <- this is close to the equilivent Iam looking for in vb.net except its in c#.


    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr




    • Edited by The Thinker Wednesday, July 17, 2013 10:10 PM edit 6
    Wednesday, July 17, 2013 10:04 PM
  • I cannot try the code, I only can read and try to understand

    If I understand it right, 

      1) you create/get the data from a VB assembly

      2) you then pass this data to a C++ assembly (To this point, no problem, the data marshals)

      3) then you pass the data to a driver (An it is there that it crash, the driver don't like the structure of the data you are passing)

    --------------

     If this is right, and also if from VBScript you can get it to work, I have to conclude that on the C++ side, you are able to create an array/structure that is acceptable by the driver.

    Then Have you try to create a new array in C++ and just recopy the data recieved from VB to it? And then pass this new copy to the driver. This way, the data will be to an acceptable form for the driver.

    It does not bluescreen me the driver just does not see those parameters so it does nothing with the data (I have a messagebox on c++ side telling me if the data passed correctly and safe array type/parameters). But vbscript passes those parameters and it lets them through. This is from microsofts dsf(device simulation framework) libraries but I need softhidreceiver.dll which is unmanaged. It is a c/c++ com dll but Iam not for sure how I would hybrid it out. 

    For #1 and #2 yes that is correct except for the parameters to the function.  I have not tried passing my system.array variable above as a pointer to the c++ function though so I do not know fully if it will work from vb.net yet or not. If I knew how to convert the c/c++ unmanaged com code to dotnet dll I would do it but that would probably require some time recoding everything as it has some custom code in spots I noticed on the c++ side that might not convert at all.

    Is it true that in c# you can  declare pointers similar to c++ such as: byte[] *myptr; <- this is close to the equilivent Iam looking for in vb.net except its in c#.


    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr





    If you look on my kinect multipoint page here: http://kinectmultipoint.codeplex.com you should be able to play around with the c++ dll i was talking about and the full vb.net source. You just need the dsf runtime from the wdk (not the code parts just the runtime which contains dlls and system files and services) and the dlls in the bin folder of the dsf mouse wrapper library vb.net version on the downloads section. I can upload the part I have done now but its not much change except for the structure is their instead of declaring the system.array locally in the sendinputreport function. Hope that would help some. I would hate to convert it in c++ because of the possibility their are no ways to get some functions or subs in c++ to show to dotnet.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr

    Wednesday, July 17, 2013 11:12 PM
  • I cannot try the code, I only can read and try to understand

    If I understand it right, 

      1) you create/get the data from a VB assembly

      2) you then pass this data to a C++ assembly (To this point, no problem, the data marshals)

      3) then you pass the data to a driver (An it is there that it crash, the driver don't like the structure of the data you are passing)

    --------------

     If this is right, and also if from VBScript you can get it to work, I have to conclude that on the C++ side, you are able to create an array/structure that is acceptable by the driver.

    Then Have you try to create a new array in C++ and just recopy the data recieved from VB to it? And then pass this new copy to the driver. This way, the data will be to an acceptable form for the driver.

    It does not bluescreen me the driver just does not see those parameters so it does nothing with the data (I have a messagebox on c++ side telling me if the data passed correctly and safe array type/parameters). But vbscript passes those parameters and it lets them through. This is from microsofts dsf(device simulation framework) libraries but I need softhidreceiver.dll which is unmanaged. It is a c/c++ com dll but Iam not for sure how I would hybrid it out. 

    For #1 and #2 yes that is correct except for the parameters to the function.  I have not tried passing my system.array variable above as a pointer to the c++ function though so I do not know fully if it will work from vb.net yet or not. If I knew how to convert the c/c++ unmanaged com code to dotnet dll I would do it but that would probably require some time recoding everything as it has some custom code in spots I noticed on the c++ side that might not convert at all.

    Is it true that in c# you can  declare pointers similar to c++ such as: byte[] *myptr; <- this is close to the equilivent Iam looking for in vb.net except its in c#.


    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr





    If you look on my kinect multipoint page here: http://kinectmultipoint.codeplex.com you should be able to play around with the c++ dll i was talking about and the full vb.net source. You just need the dsf runtime from the wdk (not the code parts just the runtime which contains dlls and system files and services) and the dlls in the bin folder of the dsf mouse wrapper library vb.net version on the downloads section. I can upload the part I have done now but its not much change except for the structure is their instead of declaring the system.array locally in the sendinputreport function. Hope that would help some. I would hate to convert it in c++ because of the possibility their are no ways to get some functions or subs in c++ to show to dotnet.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr


    Nevermind, I set the flags above on the c++ side and it did not help at all. I think it might be the way the data is being interoped to c++ from the managed side. I'll just start a new thread with my information from the common language runtime forum I tried to get an answer on.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr

    • Marked as answer by The Thinker Thursday, July 18, 2013 5:50 PM
    Thursday, July 18, 2013 5:50 PM