en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en es en en en en en en en en en zh en en en en en en en en en en en en en es en en en en en en en en en en en en en nb en en en en en en en es en en en en en en en en ar en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en es en en en en es en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en es en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en pt en en en en en en en en en en en en en en en en en en en en en en en en en en en en en de en en en fr en en en en en en en en en pt en en en en en en
By logging into your account, you agree to our Privacy Policy, personal data processing and storage practices as described therein.
Forgot password or user name?
Search in titles only Search in COM Programming only
You are not logged in. You can browse in the PowerBASIC Community, but you must click Login (top right) before you can post. If this is your first visit, check out the FAQ or Sign Up.
All Time Today Last Week Last Month
All Discussions only Photos only Videos only Links only Polls only Events only
Previous 1 2 template Next
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."
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.
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 through 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.
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 through ADO using the Oracle OLE provider as a VT_DECIMAL.
2 Oct 2009, 06:39 PM
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...
.. 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.
2 Oct 2009, 04:58 PM
(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):
' 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
2 Oct 2009, 09:42 AM
>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.
1 Oct 2009, 06:14 PM
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.
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.
// 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.
' **************************************************************************************** ' 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 '   nOffset AS LONG '   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 () AS STRING Property SET Text (IN BYVAL rhs AS STRING) Property GET TextLoc () AS udtTextLoc Property SET TextLoc (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.
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:
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
1 Oct 2009, 05:16 PM
Exactly, the COM subsystem does all the work when the client uses Automation.
1 Oct 2009, 04:58 PM
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.
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.
1 Oct 2009, 03:19 PM
Maybe it's the PB compiler via the dispatch interface (OBJECT GET...TO var , OBJECT CALL.... TO var) which always returns a VARIANT?
1 Oct 2009, 02:43 PM
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.
1 Oct 2009, 08:30 AM
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."
30 Sep 2009, 03:59 PM
It says they are uint64 in de M$ docs: http://msdn.microsoft.com/en-us/libr...32(VS.85).aspx
30 Sep 2009, 03:29 PM
>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.
30 Sep 2009, 11:49 AM
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:
so I can get the driveletters with the physical drive...
30 Sep 2009, 10:56 AM
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
30 Sep 2009, 10:53 AM
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.
30 Sep 2009, 10:40 AM
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)...
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
30 Sep 2009, 10:40 AM
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.
30 Sep 2009, 10:35 AM
Add to display for each line the VARIANTVT() of vRes.
You have things in there like
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.
Previous 1 2 template Next
Copyright © 1998-2022 PowerBASIC Tools, LLC - All Rights Reserved.
Powered by vBulletin® Version 5.7.0
Copyright © 2022 vBulletin Solutions, Inc. All rights reserved.
All times are GMT-5. This page was generated at 02:02 AM.
We process personal data about users of our site, through the use of cookies and other technologies, to deliver our services, and to analyze site activity. For additional details, refer to our Privacy Policy.
By clicking "I AGREE" below, you agree to our Privacy Policy and our personal data processing and cookie practices as described therein. You also acknowledge that this forum may be hosted outside your country and you consent to the collection, storage, and processing of your data in the country where this forum is hosted.