Announcement

Collapse
No announcement yet.

Variant and uint64

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Michael Mattias
    replied
    I don't see what relevance your discussion about what is and is not expected of Variant# has to the original question.
    ????

    Sentence One, Post One, this thread:
    How do I retrieve an unsigned quad (UINT64) from a Variant? I tried several things and they all return '0'... For instance Variant#(MyVariant) also returns '0'. Do I need to use VariantVT() somehow?
    Call me crazy, that sure reads as though the original question was about what should be expected of VARIANT#(). The stuff about "Call @@var" and The Sacred and Holy Mysteries of Automation Datatypes was interesting, but I don't think it got an answer.

    My answer - in case it got lost in the shuffle here - was "yes, you DO need to use VARIANTVT, and don't go calling that a compiler problem because you were the one who asked to receive a VARIANT datatype in your code."

    Leave a comment:


  • Dominic Mitchell
    replied
    And so what automation doesn't support 64 bit integers? Totally irrelevant!
    It is very relevant to the original question because it explains why the return value is VT_BSTR.

    I don't see what relevance your discussion about what is and is not expected of Variant# has to the original question.
    By the way, COM provides the VariantChangeType/VariantChangeTypeEx functions that allow a programmer to change the data type of a variant.

    Huh? I never said anyone's doc was wrong.
    That was directed at José.

    By the way, this is not a universal truth.

    The Oracle DB returns NUMBER(11,0) columns thru ADO using the Oracle OLE provider as a VT_DECIMAL.
    Authors handle this automation limitation differently. VT_DECIMAL is automation-compatible, VT_UI8 is not.
    Last edited by Dominic Mitchell; 2 Oct 2009, 08:35 PM.

    Leave a comment:


  • Michael Mattias
    replied
    The value is converted to a VT_BSTR because 64-bit integers are not supported by Automation.
    By the way, this is not a universal truth.

    The Oracle DB returns NUMBER(11,0) columns thru ADO using the Oracle OLE provider as a VT_DECIMAL.

    MCM

    Leave a comment:


  • Michael Mattias
    replied
    The documentation is correct. The value is converted to a VT_BSTR because 64-bit integers are not
    Huh? I never said anyone's doc was wrong. I said PB VARIANT#() does not convert type VT_DECIMAL, which I believe qualifies as a "numeric" variant data type.

    And so what automation doesn't support 64 bit integers? Totally irrelevant!

    What is at issue here is, should...
    Code:
    Z = VARIANT#(variant_Var)
    .. return anything other than zero when the VARIANTVT(variant_var) equals VT_BSTR?

    That is, dare it assume the BSTR is a character zoned decimal?

    I don't think so. You may disagree.

    MCM

    Leave a comment:


  • Dominic Mitchell
    replied
    (While I am doing this, you should make a note that VARIANT#() also does not handle VT_DECIMAL types,
    but there is code here to handle that for you). (Yes, I have submitted a new feature suggestion for same).
    Then again, maybe you think it is reasonable, in which case you should submit the New Feature Suggestion
    to which I alluded earlier in this thread.
    Huh!? How is that going to help here?

    The documentation is correct. The value is converted to a VT_BSTR because 64-bit integers are not
    supported by Automation. See the table below.
    Also, see info at the following link(click the numbers link):
    http://msdn.microsoft.com/en-us/libr...16(VS.85).aspx

    Code:
    ' Variant type usage key
    '
    ' * [V] - may appear in a VARIANT
    ' * [T] - may appear in a TYPEDESC
    ' * [P] - may appear in an OLE property set
    ' * [S] - may appear in a Safe Array
    '
    '  VT_EMPTY            [V]   [P]     nothing
    '  VT_NULL             [V]   [P]     SQL style Null
    '  VT_I2               [V][T][P][S]  2 byte signed int
    '  VT_I4               [V][T][P][S]  4 byte signed int
    '  VT_R4               [V][T][P][S]  4 byte real
    '  VT_R8               [V][T][P][S]  8 byte real
    '  VT_CY               [V][T][P][S]  currency
    '  VT_DATE             [V][T][P][S]  date
    '  VT_BSTR             [V][T][P][S]  OLE Automation string
    '  VT_DISPATCH         [V][T][P][S]  IDispatch *
    '  VT_ERROR            [V][T][P][S]  SCODE
    '  VT_BOOL             [V][T][P][S]  True=-1, False=0
    '  VT_VARIANT          [V][T][P][S]  VARIANT *
    '  VT_UNKNOWN          [V][T]   [S]  IUnknown *
    '  VT_DECIMAL          [V][T]   [S]  16 byte fixed point
    '  VT_RECORD           [V]   [P][S]  user defined type
    '  VT_I1               [V][T][P][s]  signed char
    '  VT_UI1              [V][T][P][S]  unsigned char
    '  VT_UI2              [V][T][P][S]  unsigned short
    '  VT_UI4              [V][T][P][S]  unsigned short
    '  VT_I8                  [T][P]     signed 64-bit int
    '  VT_UI8                 [T][P]     unsigned 64-bit int
    '  VT_INT              [V][T][P][S]  signed machine int
    '  VT_UINT             [V][T]   [S]  unsigned machine int
    '  VT_VOID                [T]        C style void
    '  VT_HRESULT             [T]        Standard return type
    '  VT_PTR                 [T]        pointer type
    '  VT_SAFEARRAY           [T]        (use VT_ARRAY in VARIANT)
    '  VT_CARRAY              [T]        C style array
    '  VT_USERDEFINED         [T]        user defined type
    '  VT_LPSTR               [T][P]     null terminated string
    '  VT_LPWSTR              [T][P]     wide null terminated string
    '  VT_FILETIME               [P]     FILETIME
    '  VT_BLOB                   [P]     Length prefixed bytes
    '  VT_STREAM                 [P]     Name of the stream follows
    '  VT_STORAGE                [P]     Name of the storage follows
    '  VT_STREAMED_OBJECT        [P]     Stream contains an object
    '  VT_STORED_OBJECT          [P]     Storage contains an object
    '  VT_BLOB_OBJECT            [P]     Blob contains an object
    '  VT_CF                     [P]     Clipboard format
    '  VT_CLSID                  [P]     A class ID
    '  VT_VECTOR                 [P]     simple counted array
    '  VT_ARRAY            [V]           SAFEARRAY*
    '  VT_BYREF            [V]           void* for local use
    '  VT_BSTR_BLOB                      Reserved for system use

    Leave a comment:


  • Michael Mattias
    replied
    >demonstrate the fallacy of your statement,

    I made no statement other than that of a belief, a belief which since been shown mistaken.

    My point was, when 'something' returns a VARIANT - by whatever means - the PROGRAMMER is responsible for interrogating the data type (VARIANTVT()) and effecting any conversion to the datatype required in his/her program. It is simply not reasonable to expect the compiler to know that a VT_BSTR is a valid datatype suitable for conversion to a numeric variable using the VARIANT#() function, simply because this time that BSTR just happens to contain something which could be interpreted as a character zoned decimal number.

    Then again, maybe you think it is reasonable, in which case you should submit the New Feature Suggestion to which I alluded earlier in this thread.

    MCM

    Leave a comment:


  • Dominic Mitchell
    replied
    Michael, to demonstrate the fallacy of your statement, I will provide an example.

    The following is the PowerBASIC code that implements the TextLoc property of an ActiveX control.
    It returns an HRESULT and has an out parameter that returns a struct. Notice not a single variant is used.
    Code:
    FUNCTION treeINode_get_TextLoc(BYVAL pThis AS DWORD, pTextLoc AS udtTextLoc) AS LONG
    
      LOCAL trc           AS RECT
      LOCAL pTreeCtl      AS ITreeControl PTR
      LOCAL pttid         AS INode PTR
      LOCAL pCIFace       AS CIFace PTR
      LOCAL pCIFace2      AS CIFace PTR
      LOCAL pINodes       AS DWORD
      LOCAL pLoc          AS udtTextLoc PTR
      LOCAL hr            AS LONG
    
      pttid = pThis
    
      pCIFace = pThis
      pINodes = @pCIFace.pObject
    
      pCIFace2 = pINodes
      pTreeCtl = @pCIFace2.pObject
    
      IF VARPTR(pTextLoc) = %NULL THEN
        FUNCTION = %E_POINTER
        EXIT FUNCTION
      END IF
    
      hr = %E_FAIL
    
      trc.nLeft = %TGIR_LABEL
      IF SendMessage(@pTreeCtl.m_hWnd, %TRM_GETITEMRECT, pThis, BYVAL VARPTR(trc)) THEN
        IF treeINode_get_Text(pThis, pTextLoc.bstrText) = %S_OK THEN
          pTextLoc.nOffset = trc.nTop
          hr = %S_OK
        END IF
      END IF
    
      FUNCTION = hr
    
    END FUNCTION
    The following is an excerpt from the IDL file for the control. The interface is defined as dual
    because we want to allow both direct Vtbl binding and Automation.
    Note: In the following excerpts only the methods of interest have been included.
    Code:
      // The following two structs are here to test IRecordInfo and are not part of this library.
      typedef [uuid(DDC45BA7-C40E-4EB1-9554-417897C31885)]
      struct udtTextLoc {
        BSTR bstrText;
        long nOffset;
      } udtTextLoc;
    
      [
        uuid(18C9C171-C7B0-456C-B8D6-67AC59B40D7D),
        helpstring("An object in a tree control that can contain images and text."),
        hidden,
        dual,
        nonextensible,
        oleautomation
      ]
      interface ITreeNode : IDispatch
      {
        [id(0x00000019), propget, helpstring("Returns/sets a user-defined type.")]
        HRESULT TextLoc([out, retval] udtTextLoc* Location);
        [id(0x00000019), propput, helpstring("Returns/sets a user-defined type.")]
        HRESULT TextLoc([in] udtTextLoc* Location);
      };
    The following is an excerpt from the include file generated for the PowerBASIC compiler.
    Code:
    ' ****************************************************************************************
    ' Library Name: TreeControl
    ' Library ID:   {9D39F2C1-7047-438F-9620-5F7E2692A67F}
    ' Library File: F:\Phoenix3\COM\TreeCtl\Bin\TreeCtl.dll
    ' Description:  TreeCtl 1.0
    ' Code generated by Phoenix Visual Designer
    ' ****************************************************************************************
    
    ' ****************************************************************************************
    ' ProgIDs (Program identifiers)
    ' ****************************************************************************************
    
    $PROGID_PROMETHEUSTREECONTROL1                               = "Prometheus.TreeControl.1"
    
    ' ****************************************************************************************
    ' udtTextLoc
    ' uuid: {DDC45BA7-C40E-4EB1-9554-417897C31885}
    ' ****************************************************************************************
    
    TYPE udtTextLoc
      bstrText  	AS STRING PTR                                   ' <VT_BSTR>
      nOffset   	AS LONG                                         ' <VT_I4>
    END TYPE
    
    ' ****************************************************************************************
    ' coclass:        TreeControl
    ' clsid:          {24D9B84A-BED7-4EA2-888E-F291EB80320D}
    ' ProgID:         Prometheus.TreeControl
    ' Version ProgID: Prometheus.TreeControl.1
    ' Description:    Prometheus ActiveX Tree Control
    ' Type Flags:     [cancreate, control]
    ' ----------------------------------------------------------------------------------------
    ' Interface:      ITree
    ' uuid:           {0CCED9FC-7D43-4CC0-BE9C-12F3790AC8B9}
    ' Description:    Displays a hierarchical list of Node objects, each of which consists of a label and an optional bitmap.
    ' Type Flags:     [hidden, dual, nonextensible, dispatchable]
    ' ****************************************************************************************
    
    $CLSID_PROMETHEUSTREECONTROL = GUID$("{24D9B84A-BED7-4EA2-888E-F291EB80320D}")
    $IID_PROMETHEUSTREECONTROL   = GUID$("{0CCED9FC-7D43-4CC0-BE9C-12F3790AC8B9}")
    
    ' ****************************************************************************************
    ' coclass:        TreeNode
    ' clsid:          {0C154109-C88D-400D-B215-04C112AF4DDB}
    ' Description:    An object in a tree control that can contain images and text.
    ' ----------------------------------------------------------------------------------------
    ' Interface:      ITreeNode
    ' uuid:           {18C9C171-C7B0-456C-B8D6-67AC59B40D7D}
    ' Description:    An object in a tree control that can contain images and text.
    ' Type Flags:     [hidden, dual, nonextensible, dispatchable]
    ' ****************************************************************************************
    
    $CLSID_PROMETHEUSTREENODE = GUID$("{0C154109-C88D-400D-B215-04C112AF4DDB}")
    $IID_PROMETHEUSTREENODE   = GUID$("{18C9C171-C7B0-456C-B8D6-67AC59B40D7D}")
    
    INTERFACE PrometheusTreeNode $IID_PROMETHEUSTREENODE
      INHERIT Dual
      Property GET Text<&H00000000>() AS STRING
      Property SET Text<&H00000000>(IN BYVAL rhs AS STRING)
      Property GET TextLoc<&H00000019>() AS udtTextLoc
      Property SET TextLoc<&H00000019>(IN BYREF rhs AS udtTextLoc)
    END INTERFACE
    So far there isn't a single variant in sight. But look at what happens when the location of text
    is retrieved using Automation.
    Code:
    LOCAL oNode     AS INode
    LOCAL vLoc      AS VARIANT
    
    OBJECT GET oNode.TextLoc TO vLoc
    What is going on here?
    The COM subsystem using information from the type library allocates memory for the struct(let's call it pTextLoc)
    and invokes TextLoc. It then passes back to the client a variant containing the following values:
    Code:
     
    vLoc.vt = %VT_RECORD
    vLoc.br.pvRecord = pTextLoc     <-- address of memory allocated for struct
    vLoc.br.pRecInfo = pIRecordInfo <-- a pointer to an instance of an IRecordInfo that describes the struct

    Leave a comment:


  • Dominic Mitchell
    replied
    Exactly, the COM subsystem does all the work when the client uses Automation.

    Leave a comment:


  • José Roca
    replied
    When using Automation, what PB (and any other language that supports Automation) does is to fill an array of variants with the values and types of the parameters and call the Invoke method of the IDispatch interface. The server will delegate the call to the standard DispInvoke function or implement its own code, in which case it has to unpack the parameters, call the method or property and fill the pvarResult parameter of the Invoke method with the return value.

    See: http://msdn.microsoft.com/en-us/library/ms221479.aspx

    But the methods themselves can use any kind of types if using direct interface calls or any kind of Automation-compatible types if using Automation. This applies both to the parameters and the return values.

    Leave a comment:


  • Michael Mattias
    replied
    Maybe it's the PB compiler via the dispatch interface (OBJECT GET...TO var , OBJECT CALL.... TO var) which always returns a VARIANT?

    Leave a comment:


  • Dominic Mitchell
    replied
    I believe COM properties and methods always return a VARIANT, which the compiler/interpreter product
    may or may not convert/cast to something handy.
    Really!? Methinks you have got that backwards.

    Think back to the code used to access the methods of a COM server using version 8.xxx of the compiler.
    While you are at it, have a look at the type library(not the generated include file) for that server.
    Think Automation and Automation-compatible data types.

    Leave a comment:


  • Michael Mattias
    replied
    Those docs apply to programming in WMI script.

    I believe COM properties and methods always return a VARIANT, which the compiler/interpreter product may or may not convert/cast to something handy.

    Sounds like WMISCRIPT converts it to something handy. But I cannot find fault with the compiler design here... the variant it gets back is a VT_BSTR and you can't really expect it to guess that string - this time - is 'really' a zoned character decimal and therefore VARIANT#() should be able to cast it to a numeric datatype.

    I suppose you could put in a new feature suggestion to ask that when VARIANT#() is called against VT_BSTR it perform the equivalent of VAL() on it.

    But I would think the programmer should know, "when I call this method/property, I expect a number/string/date and therefore I must convert whatever the VARIANTVT() supplied happens to be to that target data type."

    MCM

    Leave a comment:


  • Peter Lameijn
    replied
    It says they are uint64 in de M$ docs: http://msdn.microsoft.com/en-us/libr...32(VS.85).aspx

    Leave a comment:


  • Michael Mattias
    replied
    >So it's a MS flaw after all... Size, TotalCylinders and TotalSectors are UINT64
    > ("replaced with Size, TotalCylinders and TotalSectors return a string") ...
    > Totalheads a UINT32

    Where does it say Size, TotalCylinders and TotalSectors are uint64? When you generate the COM interface file, everything always comes back a VARIANT....which means the burden is on you to query the returned VARIANTVT an retrieve and assign to a suitable variable.

    I really don't want to say, "that's the beauty of the VARIANT datatype", but it is.

    MCM

    Leave a comment:


  • Peter Lameijn
    replied
    Thanks all,

    So it's a MS flaw after all... It would have been nice if they were consistent. (But I don't think that word is in their vocabulary )
    Size, TotalCylinders and TotalSectors return a string, Totalheads a UINT32...

    I now am going to try to implement this code:
    http://www.powerbasic.com/support/pb...0&postcount=16
    so I can get the driveletters with the physical drive...

    Leave a comment:


  • Michael Mattias
    replied
    Methinks Jose hit the jackpot by testing for and finding VT_BSTR.

    FWIW, this demo contains code you can cut and paste when you need to deal with the possibility of 'many different VT_xxxxx' (includes functions for VT_DECIMAL, VT_DATE and VT_ARRAY|VT_UI1) ...

    Generic 'ADO' Connection and Query Tester (CC 5+/Win 9+) 11-02-08

    MCM

    Leave a comment:


  • Edwin Knoppert
    replied
    Do note that a variant *can* be set to a vartype but not having any data.
    The remark above about null string is incorrect.
    I have met a situation that a vartype was set but a 'null' as value (pointer).
    The PB app gpf'ed.
    If you don't trust a certain com result you must test both vartype and data.

    This was submitted to support a few months ago.

    Leave a comment:


  • Michael Mattias
    replied
    OR.....

    You could be running into compiler assumptions about the required intermediate data types when doing everything within an expression.

    For the numeric returns, try (as demonstrated above)...

    Code:
    LOCAL Q AS QUAD 
    ...
    Object Get oItem.TotalSectors To vRes
    Q =   VARIANT#(vRes)
    Disp = Disp & $Cr & "Sectors: "  & $Tab & FORMAT$(Q, 18) 'specify max possible decimal digits
    MCM

    Leave a comment:


  • José Roca
    replied
    Peter,

    It doesn't return VT_NULL, but 8 (VT_BSTR), a dynamic unicode string (clean your glasses ). This is why VARIANT$ returns the correct result. I know that the M$ documentation says that it returns an unsigned 64-bit integer, but you can't blindly trust M$.

    I guess that they changed his mind and returned an string instead because many compilers don't support unsigned 64-bit integers.

    Leave a comment:


  • Michael Mattias
    replied
    Add to display for each line the VARIANTVT() of vRes.

    Then post output.

    You have things in there like
    Code:
    Object Get oItem.TotalSectors To vRes
    Disp = Disp & $Cr & "Sectors: "  & $Tab & Variant$(vRes) 'Format$(Variant#(vRes))
    Seems to me "total sectors" should be numeric and your commented out FORMAT$(VARIANT#(vRes)) should be the correct thing to use.

    You may be getting something like VT_DECIMAL, or even a VT_ARRAY|VT_UI1 back, and VARIANT#() is just not prepared for it, e.g., my reference above to a known (to me and PB if nobody else) bug when VARIANTVT returns VT_DECIMAL.

    I suppose I could try it but I'm just a shiftless lazy person of questionable legitimacy.

    MCM

    Leave a comment:

Working...
X