Results 1 to 9 of 9

Thread: [RESOLVED] VB6 - Unsigned data type (Can I trick?)

  1. #1

    Thread Starter
    PowerPoster Dave Sell's Avatar
    Join Date
    Mar 2004
    Location
    /dev/null
    Posts
    2,961

    Resolved [RESOLVED] VB6 - Unsigned data type (Can I trick?)

    OK I'm not very hopeful of a resolution but I thought I'd give it a shot here.

    I have an OPC Simulator that I can create "in-memory arrays". These arrays can be of various data types. For example they can be VT_I2, VT_I4, VT_UI2, etc...

    If these look familiar to you then keep reading... AFAIK I2 = Signed Integer, I4 = Singed Long (both native VB6 data types). Ergo, UI2 = Unsigned Integer, however VB6 cannot declare a variable as an Unsigned Int or Long (a known limitation to VB6).

    As you may have guessed, I have successfully Read data from and Written data to the VT_I2 and the VT_I4 arrays, but am unable to Write to the VT_UI2 array (although strangely I can read from it).

    I will try to condense all the code as small as possible.

    VB Code:
    1. Public Enum CanonicalDataTypes
    2.     CanonDtShort = 2 ' VT_I2
    3.     CanonDtLong = 3 ' VT_I4
    4.     CanonDtFloat = 4
    5.     CanonDtDouble = 5
    6.     CanonDtString = 8
    7.     CanonDtBool = 11
    8.     CanonDtChar = 16
    9.     CanonDtByte = 17
    10.     CanonDtWord = 18 ' VT_UI2
    11.     CanonDtDword = 19 ' VT_UI4
    12.     CanonDtArray = 8192 ' VT_Array
    13. End Enum

    The following code works for Longs (VT_I4):

    VB Code:
    1. Sub AddOPCItem
    2.     '
    3.     Dim Types(1) As Integer
    4.     '
    5.     ' Works:
    6.     '
    7.     ' VT_I4
    8.     OPCItemIDs(1) = "Device_1.aLong"
    9.     Types(1) = CanonDtLong + CanonDtArray
    10.     '
    11.     ' ...
    12.     '
    13.     Dim RequestedDataType As Variant
    14.     RequestedDataType = CVar(Types)
    15.     '
    16.     OPCItemCollection.AddItems ItemCount, OPCItemIDs, ClientHandles, ItemServerHandles, ItemServerErrors, RequestedDataType
    17.     '
    18. End Sub
    19.  
    20. Sub WriteOPC
    21.     '
    22.     Dim Vals(4) As Long ' DHS good for LONGs (VT_I4)
    23.     '
    24.     For i = 1 To 4
    25.         Vals(i) = CLng("SomeNumericValue")
    26.     Next
    27.     '
    28.     ' ...
    29.     '
    30.     ASyncItemValues(1) = CVar(Vals)
    31.     ConnectedGroup.AsyncWrite ItemCount, ASyncItemServerHandles, ASyncItemValues, ASyncItemServerErrors, TransactionID, CancelID
    32.     '
    33. End Sub

    The following code works for Integers (VT_I2):

    VB Code:
    1. Sub AddOPCItem
    2.     '
    3.     Dim Types(1) As Integer
    4.     '
    5.     ' Works:
    6.     '
    7.      VT_I2
    8.     OPCItemIDs(1) = "Device_1.aShort"
    9.     Types(1) = CanonDtShort + CanonDtArray
    10.     '
    11.     ' ...
    12.     '
    13.     Dim RequestedDataType As Variant
    14.     RequestedDataType = CVar(Types)
    15.     '
    16.     OPCItemCollection.AddItems ItemCount, OPCItemIDs, ClientHandles, ItemServerHandles, ItemServerErrors, RequestedDataType
    17.     '
    18. End Sub
    19.  
    20. Sub WriteOPC
    21.     '
    22.     Dim Vals(4) As Integer ' DHS - good for SHORTs (VT_I2)
    23.     '
    24.     For i = 1 To 4
    25.         Vals(i) = CInt("SomeNumericValue")
    26.     Next
    27.     '
    28.     ' ...
    29.     '
    30.     ASyncItemValues(1) = CVar(Vals)
    31.     ConnectedGroup.AsyncWrite ItemCount, ASyncItemServerHandles, ASyncItemValues, ASyncItemServerErrors, TransactionID, CancelID
    32.     '
    33. End Sub

    As you can see I can define a VB array of Integers to Write data down to VT_I2's and I can define a VB array of Longs to Write data down to VT_I4's.

    However I am unable to create a VB array such that I can Write down to VT_UI2's or VT_UI4's.

    I have tried using VB arrays of Integers and VB arrays of Longs in an attempt to Write data down to the VT_UI2 and VT_UI4 OPC arrays, but no data gets written down. No error is reported on either end. Its just like nothing happens.

    Question: Can I create a VB Array of "Somethings" to trick the transport layer into accepting something as an Unsigned data type?

    I have seen some blurbs about SAFEARRAYs but am unsure how that fits into the equation...

    Thanks!

    Dave
    Last edited by Dave Sell; May 13th, 2009 at 02:48 PM.
    Nobody knows what software they want until after you've delivered what they originally asked for.

    Don't solve problems which don't exist.

    "If I had eight hours to cut down a tree, I'd spend six hours sharpening my axe." --- Abraham Lincoln (1809-1865)

    2 idiots don't make a genius.

  2. #2
    VB6, XHTML & CSS hobbyist Merri's Avatar
    Join Date
    Oct 2002
    Location
    Finland
    Posts
    6,654

    Re: VB6 - Unsigned data type (Can I trick?)

    If I understood correctly, you are passing the arrays within a Variant. This means you can do a very simple trick: use PutMem2 (or RtlMoveMemory) to change the type of the Variant so that VB6 can use it.

    This sample demonstrates how you can find the type value:
    Code:
    Option Explicit
    
    Private Declare Sub GetMem2 Lib "msvbvm60" (ByRef Var As Any, ByRef Value As Integer)
    Private Declare Sub PutMem2 Lib "msvbvm60" (ByRef Var As Any, ByVal Value As Integer)
    
    Private Sub Form_Load()
        Dim intType As Integer, lngTest() As Long, varTest As Variant
        ReDim lngTest(0)
        varTest = lngTest
        GetMem2 varTest, intType
        Debug.Print Hex$(intType)
        PutMem2 varTest, &H2013
        ' automation error (because VB does not support unsigned integers except Byte)
        Debug.Print varTest(0)
    End Sub
    I guess this is enough for you to figure out the rest


    Edit!
    Patching brain gas leak.
    Last edited by Merri; May 13th, 2009 at 03:33 PM.

  3. #3
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: VB6 - Unsigned data type (Can I trick?)

    Have you tried to use a byte array vs long/integer for the unsigned?

    Writing the unsigned values to the byte array would be a bit of work, but not too difficult.

    As a test, dim Vals(3) As Byte, then change Vals(3)=1 and see if your OPC control accepts the byte array. If it does, then you'd only need some code to copy the unsigned to the byte array.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  4. #4
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: VB6 - Unsigned data type (Can I trick?)

    Hey got another idea if any of the above don't work. I am guessing that your OPC control is checking the variant type of the passed variant and if it isn't UI4 then it is ignoring it. So, how about forcing the issue with CopyMemory API...

    Code:
    Dim vData As Variant, vType As Integer
    vType = &H2000 Or 19 ' array of UI4
    vData = CVar(Vals())
    ' write to the variant structure what type of data it contains
    CopyMemory ByVal VarPtr(vData), vType, 2&
    ' now the variant thinks it is UI4; how now?
    ASyncItemValues(1) = vData
    If it works, UI2 is &H2000 Or 18
    Listing of Variant Type codes


    Edited: I see I pretty much repeated what Merri posted. Even though VB can't use the vData variant while it thinks it is UI4, your OPC should be able to. If the vData variant needs to be read by your VB app, then you'd have to change the UI4 to simply I4 which is &H2000 Or 3 for a an array of longs; then you'd be able to read the data back using VB.
    Last edited by LaVolpe; May 13th, 2009 at 03:53 PM.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  5. #5

    Thread Starter
    PowerPoster Dave Sell's Avatar
    Join Date
    Mar 2004
    Location
    /dev/null
    Posts
    2,961

    Re: VB6 - Unsigned data type (Can I trick?)

    Quote Originally Posted by LaVolpe View Post
    Have you tried to use a byte array vs long/integer for the unsigned?

    Writing the unsigned values to the byte array would be a bit of work, but not too difficult.

    As a test, dim Vals(3) As Byte, then change Vals(3)=1 and see if your OPC control accepts the byte array. If it does, then you'd only need some code to copy the unsigned to the byte array.

    I tried Dim Vals(4) as Byte - I get the "no reaction", where I can read the values but when I try to do a Write, nothing happens.

    I believe the data type Byte is too small.

    Can i do something like:

    Dim Vals(4) as Byte(2)?
    Nobody knows what software they want until after you've delivered what they originally asked for.

    Don't solve problems which don't exist.

    "If I had eight hours to cut down a tree, I'd spend six hours sharpening my axe." --- Abraham Lincoln (1809-1865)

    2 idiots don't make a genius.

  6. #6

    Thread Starter
    PowerPoster Dave Sell's Avatar
    Join Date
    Mar 2004
    Location
    /dev/null
    Posts
    2,961

    Re: VB6 - Unsigned data type (Can I trick?)

    Quote Originally Posted by LaVolpe View Post
    Hey got another idea if any of the above don't work. I am guessing that your OPC control is checking the variant type of the passed variant and if it isn't UI4 then it is ignoring it. So, how about forcing the issue with CopyMemory API...

    Code:
    Dim vData As Variant, vType As Integer
    vType = &H2000 Or 19 ' array of UI4
    vData = CVar(Vals())
    ' write to the variant structure what type of data it contains
    CopyMemory ByVal VarPtr(vData), vType, 2&
    ' now the variant thinks it is UI4; how now?
    ASyncItemValues(1) = vData
    If it works, UI2 is &H2000 Or 18
    Listing of Variant Type codes


    Edited: I see I pretty much repeated what Merri posted. Even though VB can't use the vData variant while it thinks it is UI4, your OPC should be able to. If the vData variant needs to be read by your VB app, then you'd have to change the UI4 to simply I4 which is &H2000 Or 3 for a an array of longs; then you'd be able to read the data back using VB.
    I want to try this code, but CopyMemory is undefined. I tried adding this but I get an error that the entry point is undefined:

    VB Code:
    1. Private Declare Sub CopyMemory Lib "kernel32" Alias _
    2. "RTlMoveMemory" (lpDest As Any, lpSource AS Any, _
    3. ByVal cbCopy As Long)
    Nobody knows what software they want until after you've delivered what they originally asked for.

    Don't solve problems which don't exist.

    "If I had eight hours to cut down a tree, I'd spend six hours sharpening my axe." --- Abraham Lincoln (1809-1865)

    2 idiots don't make a genius.

  7. #7
    VB6, XHTML & CSS hobbyist Merri's Avatar
    Join Date
    Oct 2002
    Location
    Finland
    Posts
    6,654

    Re: VB6 - Unsigned data type (Can I trick?)

    Private Declare Sub PutMem2 Lib "msvbvm60" (ByRef Var As Any, ByVal Value As Integer)

    Code:
    Sub WriteOPC
        '
        Dim Vals(4) As Long ' DHS good for LONGs (VT_I4)
        '
        For i = 1 To 4
            Vals(i) = CLng("SomeNumericValue")
        Next
        '
        ' ...
        '
        ASyncItemValues(1) = CVar(Vals)
        ' hack
        PutMem2 AsyncItemValues(1), CanonDtArray Or CanonDtDWord
        '
        ConnectedGroup.AsyncWrite ItemCount, ASyncItemServerHandles, ASyncItemValues, ASyncItemServerErrors, TransactionID, CancelID
        '
    End Sub

  8. #8

    Thread Starter
    PowerPoster Dave Sell's Avatar
    Join Date
    Mar 2004
    Location
    /dev/null
    Posts
    2,961

    Re: VB6 - Unsigned data type (Can I trick?)

    Quote Originally Posted by Merri View Post
    Private Declare Sub PutMem2 Lib "msvbvm60" (ByRef Var As Any, ByVal Value As Integer)

    Code:
    Sub WriteOPC
        '
        Dim Vals(4) As Long ' DHS good for LONGs (VT_I4)
        '
        For i = 1 To 4
            Vals(i) = CLng("SomeNumericValue")
        Next
        '
        ' ...
        '
        ASyncItemValues(1) = CVar(Vals)
        ' hack
        PutMem2 AsyncItemValues(1), CanonDtArray Or CanonDtDWord
        '
        ConnectedGroup.AsyncWrite ItemCount, ASyncItemServerHandles, ASyncItemValues, ASyncItemServerErrors, TransactionID, CancelID
        '
    End Sub
    Wow. This actually works. I am speechless, except a BIG thanks Merri.

    Now if only I knew WHY...
    Nobody knows what software they want until after you've delivered what they originally asked for.

    Don't solve problems which don't exist.

    "If I had eight hours to cut down a tree, I'd spend six hours sharpening my axe." --- Abraham Lincoln (1809-1865)

    2 idiots don't make a genius.

  9. #9
    VB6, XHTML & CSS hobbyist Merri's Avatar
    Join Date
    Oct 2002
    Location
    Finland
    Posts
    6,654

    Re: [RESOLVED] VB6 - Unsigned data type (Can I trick?)

    Variant's first two bytes contain the type (returned by VarType function, and happen to be the same values you defined in your Enum). Thus by changing the type definition of the Variant you pass the required type and there will no longer be a silent error in the background.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width