Results 1 to 2 of 2

Thread: Parsing OLEVARIANT in VB

  1. #1

    Thread Starter
    New Member
    Join Date
    Jun 2005
    Posts
    13

    Parsing OLEVARIANT in VB

    Can anyone please tell me how to copy the safearray returned in Variant as OLEVARIANT from the IOLECOMMANDTarget.Exec, here is what I did and it works fine except only one step explained in the code below:

    I am using this:


    VB Code:
    1. Dim varIn As Variant
    2. Dim varOut As Variant
    3.  
    4. 'Here I execute the command to get block formats and it returns an OLE Variant with a pointer to safearray
    5.  
    6. IOLECoammndTarget.Exec IDM_GETBLOCKFMTS, OLECMDEXECOPT_DONTPROMPTUSER, varIn, varOut


    Here is my sub to parse the OLE Variant array returned which points to safearray.

    VB Code:
    1. Public Sub ParseOleVariantArray(varArray As Variant, Elements() As String)
    2. '
    3. ' Given a stream of bytes that represent a Microsoft SafeArray, wade through
    4. 'the garbage and get the actual data found in the array.  Write the data to disk.
    5.  
    6. '      SafeArray looks like
    7. 'typedef struct FARSTRUCT tagSAFEARRAY {
    8. '    unsigned short cDims;           // Count of dimensions in this array.
    9. '    unsigned short fFeatures;     // Flags used by the SafeArray
    10. '                                    // routines documented below.
    11. '    unsigned long cbElements; // Size of an element of the array.
    12. '                               // Does not include size of
    13. '                               // pointed-to data.
    14. '    unsigned long cLocks;  // Number of times the array has been
    15. '    void HUGEP* pvData;   // Pointer to the data.
    16. '    SAFEARRAYBOUND rgsabound[1]; // One bound for each dimension.
    17. '} SAFEARRAY;
    18. 'SAFEARRAYBOUND is a two-longword structure, the first 32 bits hold the # of
    19. 'elements in the array, the second 32 bits hold the lower bound of the array.
    20. 'There is one structure for every dimension of the array.
    21. 'http://groups-beta.google.com/group/microsoft.public.vc.vcce/browse_thread/thread/7f2bfbdb6ef17e98/a90475b71136f83b?q=OleSafeArray+visual+basic&rnum=2&hl=en#a90475b71136f83b
    22.  
    23. 'Public Type OLEVARIANT
    24. '    vt As Integer 'variable type
    25. '    wReserved1 As Integer
    26. '    wReserved2 As Integer
    27. '    wReserved3 As Integer
    28. '    lVal As Integer
    29. '    iVal As Integer
    30. '    bstrVal As Long
    31. '    pUnkVal As Long
    32. '    pArray As Long
    33. '    pvRecord As Long
    34. '    pRecInfo As Long
    35. 'End Type
    36.  
    37.     Dim pArray As Long
    38.     Dim ppArray As Long
    39.     Dim ppVarStruct As Long
    40.    
    41.     Dim intDims As Integer
    42.     Dim intFeatures As Integer
    43.     Dim lElements As Long
    44.     Dim lLocks As Long
    45.     Dim lDataPtr As Long
    46.     Dim lElementCount As Long
    47.     Dim lLbound As Long
    48.    
    49.     Dim lOffset As Long
    50.     Dim lDataTemp As Long
    51.     Dim i As Long
    52.     Dim vType As Long
    53.     '----------------------------------------------------------------
    54.     ' First get a pointer to the variant.
    55.     ppVarStruct = VarPtr(varArray)
    56.    
    57.     'Get the variable type
    58.     'CopyMemory vType, ByVal ppVarStruct, 2
    59.     'Debug.Print "vType: " & vType
    60.  
    61.     ' Get the pointer to the data *inside* the variant.  The VARTYPE is 2 bytes,
    62.     ' and each of the three reserved words are also 2 bytes, giving 8 bytes total.
    63.     '
    64.     CopyMemory ppArray, ByVal ppVarStruct + 8, 4
    65.    
    66.     ' Now parse the SafeArray structure.  The most important parts to me are the
    67.     ' Number of elements and the pointer to the actual data.
    68.     '
    69.     lOffset = 0
    70.     CopyMemory intDims, ByVal (ppArray + lOffset), ByVal Len(intDims)
    71.  
    72.     lOffset = lOffset + Len(intDims)
    73.     CopyMemory intFeatures, ByVal (ppArray + lOffset), ByVal Len(intFeatures)
    74.  
    75.     lOffset = lOffset + Len(intFeatures)
    76.     CopyMemory lElements, ByVal (ppArray + lOffset), ByVal Len(lElements)
    77.  
    78.     lOffset = lOffset + Len(lElements)
    79.     CopyMemory lLocks, ByVal (ppArray + lOffset), ByVal Len(lLocks)
    80.  
    81.     lOffset = lOffset + Len(lLocks)
    82.     CopyMemory lDataPtr, ByVal (ppArray + lOffset), ByVal Len(lDataPtr)
    83.  
    84.     lOffset = lOffset + Len(lDataPtr)
    85.     CopyMemory lElementCount, ByVal (ppArray + lOffset), ByVal Len(lElementCount)
    86.  
    87.     lOffset = lOffset + Len(lElementCount)
    88.     CopyMemory lLbound, ByVal (ppArray + lOffset), ByVal Len(lLbound)
    89.     '===============================================
    90.     Dim strElement As String
    91.    
    92.     If lElementCount > 0 Then
    93.         ReDim Elements(lElementCount)
    94.         For i = 0 To (lElementCount - 1)
    95.                 'Copy the array string element pointer to lDataTemp
    96.                 CopyMemory lDataTemp, ByVal lDataPtr, ByVal lElements
    97.                
    98.                 'strElement = Space(100)
    99.                
    100. '************************************************
    101. '************************************************
    102. '************************************************
    103. 'Here is my problem, if I comment these lines, everything works fine always, If not, after few function calls I get can not write or read memory errors and the program exits. I guess I am not copying the safearray string variables correctly from the Variantto the returned array, please help here.
    104.  
    105.                 'Copy the array string element to the variable strElement
    106.                 CopyMemory strElement, lDataTemp, ByVal lElements
    107.  
    108.                 Elements(i) = StrConv(strElement, vbFromUnicode)
    109.  
    110.                 'CopyMemory Elements(i), lDataTemp, ByVal lElements
    111. '************************************************
    112. '************************************************
    113. '************************************************                
    114.  
    115.                 'Next array element pointer
    116.                 lDataPtr = lDataPtr + lElements
    117.                 strElement = ""
    118.         Next i
    119.     End If
    120.    
    121.     'I tried to free the safearray, it works
    122.     'Debug.Print "SafeArrayDestroyData: " & SafeArrayDestroyData(ppArray)
    123.     'Debug.Print "SafeArrayDestroy: " & SafeArrayDestroy(ppArray)
    124. End Sub

    Thank you

  2. #2

    Thread Starter
    New Member
    Join Date
    Jun 2005
    Posts
    13

    Re: Parsing OLEVARIANT in VB

    I found this but it did not help in my case as this is OleVariant which I do not know if it is the same as VB Variant or not:

    http://support.microsoft.com/kb/q167668/

    How to pass a SafeArray of strings in a VARIANT* between Visual C++ and Visual Basic 6.0


    Now you can build and test the automation server. After you build the server, run it as a stand-alone to register it. Run Visual Basic 6.0 and create a new Visual Basic 6.0 project. Place a button on the form and modify the handler to match the code below:

    Private Sub Command1_Click()
    Dim o As Object
    Dim v As Variant
    ReDim v(50) As String
    Dim SortTime As Long

    Set o = CreateObject("StrArray.Document")

    upperbound = 1
    lowerbound = 100
    For n = 0 To 50
    v(n) = "Entry " & Int((upperbound-lowerbound+1)*Rnd+lowerbound)
    Next n

    SortTime = o.Sort(v)
    MsgBox ("Done")
    End Sub



    The key to getting this syntax to work in Visual Basic 6.0 is to first Dim the array variable as a variant, and then ReDim it so that it becomes a variant containing an array of strings. Now you are ready to test the server. Set break points in the Visual Basic 6.0 code before and after the call to Sort. Run the Visual Basic 6.0 application, click Command1 and use the watch window to check the values for v.

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