Theos PowerBasic Museum 2017

Archive => Discussion - Legacy Software (PBWIN 9.0+/PBCC 5.0+) => Topic started by: Paul Squires on August 22, 2008, 07:58:02 PM

Title: PB9 and Objects
Post by: Paul Squires on August 22, 2008, 07:58:02 PM
None of this post is meant to be negative. I'm just thinking out loud about a few things. I can't wait to get PB9.

I printed off the on-line help information for PB9's objects. I am trying to get a handle on it before my order for PB9 is finally filled.

I seem to understand it all but I did find it a little strange that the terminology for METHODS used "CLASS METHOD" to indicate a private method. I would have thought that "PUBLIC METHOD" or "PRIVATE METHOD" would be more intuitive because it would immediately signal to the reader the scope of the method. I guess that eventually "CLASS METHOD" will be burnt into my head to mean it is private to the Class.  :)

Also, CREATE and DESTROY for Constructors and Destructors. Would have been cool if Constructor and Destructor could have also been accepted as aliases.  :)

Not quite sure I understand the Enumerating Collections example in the Help. Are "InterfaceItem" and "InterfaceItems" already pre-existing interfaces for our use in all Classes or do we somehow need to add them to our Classes first? I still like VB's approach of using "For Each Item In Items" although I'm sure I'll get used to treating the collection like any other For/Next loop counted based on retrieving the number of objects first.

Maybe it's just me but why do new commands seem to take the form of STATEMENT VERB PARAMETER TO RESULT, I guess like the DDT functions do. It seems overly verbose. I mean GLOBALMEM ALLOC count TO vHndl. Okay, it works but vHndl = MEMALLOC(count) seems better at least in my opinionated eyes today.  :)

#INLCUDE ONCE  --  Perfect!

FORWARD REFERENCING  --  Absolutely perfect!!!

I am also a little confused about the BUILD$ fnction. Is it really practical in it's current format? I mean, I see it as the means to overcome the overhead of constantly appending of strings but in practice how would you use it. It seems like all of the strings need to exist prior to calling the function in order to get the real benefits of it, otherwise you simply end up calling the BUILD$ function repeatedly using a small number of strings (still, I can see that being more efficient over simple concatenation). I wonder if it is anymore efficient than the current method I use based on Hutch's appending code. That code essentially leaves the buffer open allowing you to continue appending strings as they become available. Maybe I'm just not visualizing it in practice. I will give it a go once I get the new compiler.  :)



   Local nPos As Long
   Local st     As String
   Local sBuffer As String

   st = "some string containing some example text"
   nPos = AppendStr2( nPos, sBuffer, StrPtr(st), Len(st) )

   st = "another string containing even more text"
   nPos = AppendStr2( nPos, sBuffer, StrPtr(st), Len(st) )

... etc... etc...

   ' Get the result of the appended string
   st = Left$( sBuffer, nPos )


'//
'//  Fast function for concatenating many strings
'//
Function AppendStr2( ByVal stPos   As Long, _
                     ByRef sBuffer As String, _
                     ByVal Addon   As Long, _
                     ByVal lenAdd  As Long _
                     ) Export As Long


    #REGISTER None

    Local pBuffer As Long
   
    ' If the buffer is not large enough to handle the adding
    ' of this string then we need to expand the buffer.
    If stPos + lenAdd + 1 > Len(sBuffer) Then
       sBuffer = sBuffer & String$( Max&(lenAdd, 32 * 1024), 0)   ' increase 32K minimum
    End If

    ' Copy the new string to the end of the buffer
    pBuffer = StrPtr(sBuffer)

    ! cld               ; Read forwards

    ! mov edi, pBuffer  ; Put buffer address In edi
    ! Add edi, stPos    ; Add starting offset To it

    ! mov esi, Addon    ; Put String address In esi
    ! mov ecx, lenAdd   ; length In ecx As counter

    ! rep movsb         ; Copy ecx count Of bytes From esi To edi

    ! mov edx, stPos
    ! Add edx, lenAdd   ; Add stPos And lenAdd For Return value

    ! mov Function, edx

End Function



Title: Re: PB9 and Objects
Post by: José Roca on August 22, 2008, 08:45:36 PM
Quote
Not quite sure I understand the Enumerating Collections example in the Help. Are "InterfaceItem" and "InterfaceItems" already pre-existing interfaces for our use in all Classes or do we somehow need to add them to our Classes first? I still like VB's approach of using "For Each Item In Items" although I'm sure I'll get used to treating the collection like any other For/Next loop counted based on retrieving the number of objects first.

It is no longer in the last version of the help file. It was a leftover of the previous help files, when using the Item property was the only compiler supported way of doing it.

Now you can use the standard IEnumVARIANT enumerator, that is what For... Each uses.


' Retrieve a reference to the collection's enumerator
DIM pEnum AS IEnumVARIANT                 ' // IEnumVARIANT interface
pEnum = pObj.NewEnum   ' All collections have a NewEnum method or property
IF ISNOTHING(pEnum) THEN ... ' Exit

' Iterate through the collection of objects
DIM vItem AS VARIANT
DIM oItem AS DISPATCH <or class name> ' if using Automation
-or-
DIM oItem AS <interface name> ' if using direct calls

DO
   ' Retrieve a reference to the next object in the collection
   ' The first parameter is the number of items to fetch.
   ' The second parameter can be an array of variants.
   ' The third variable can be a long value that will receive the number
   ' of items fetched.
   hr = pEnum.Next(1, vItem, BYVAL %NULL)
   IF hr <> %S_OK THEN EXIT DO
   ' Assign the VT_DISPATCH variant to the object variable
   oItem = vItem : vItem = EMPTY
   IF ISNOTHING(oItem) THEN EXIT DO
   ' Do other calls
   ' ...
   ' ...
   ' ...
   ' Release the object
   oItem = NOTHING
LOOP

Title: Re: PB9 and Objects
Post by: Edwin Knoppert on August 22, 2008, 08:46:14 PM
>#INLCUDE ONCE  --  Perfect!
Imo not..
Preventing the reinclusion as done before (#if NOT %DEF( ..) is better then include once.
What if a(n older) module does not have this keyword?
Title: Re: PB9 and Objects
Post by: Edwin Knoppert on August 22, 2008, 08:48:30 PM
>InterfaceItems
I don't think PB uses the IEnumerator, the example code looks the ordinary way.
Code as shown above should be the better way (aka foreach)
Title: Re: PB9 and Objects
Post by: José Roca on August 22, 2008, 08:51:18 PM
Quote from: Edwin Knoppert on August 22, 2008, 08:46:14 PM
>#INLCUDE ONCE  --  Perfect!
Imo not..
Preventing the reinclusion as done before (#if NOT %DEF( ..) is better then include once.
What if a(n older) module does not have this keyword?


You still can use #IF NOT %DEF( ..), or both at the same time. #INCLUDE ONCE means "include this file if it has not already been included".
Title: Re: PB9 and Objects
Post by: Edwin Knoppert on August 22, 2008, 10:33:50 PM

Of course i understand but now it get's discouraged to insert these few lines.
Title: Re: PB9 and Objects
Post by: José Roca on August 23, 2008, 06:24:57 AM
 
#INCLUDE ONCE is very useful with big sets of include files like my new winapi files, that also use #IF NOT %DEF. With #IF NOT %DEF, the file has still to be parsed until #ENDIF is found. With #INCLUDE ONCE, the file is not parsed at all if it has already been included. Before it was implemented, I had problems because I was exceeding the limit of nesting levels.
Title: Re: PB9 and Objects
Post by: José Roca on August 23, 2008, 06:42:41 AM
 
Quote
Maybe it's just me but why do new commands seem to take the form of STATEMENT VERB PARAMETER TO RESULT, I guess like the DDT functions do. It seems overly verbose. I mean GLOBALMEM ALLOC count TO vHndl. Okay, it works but vHndl = MEMALLOC(count) seems better at least in my opinionated eyes today.

I always have disliked the use of statements instead of functions, mainly because you always have to use a variable for the result, e.g. you can't use IF MemAlloc(count)  = 0 THEN...
Title: Re: PB9 and Objects
Post by: Patrice Terrier on August 23, 2008, 11:20:01 AM
QuoteI always have disliked the use of statements instead of functions

All SDK purist will dislike it, it is another form of DDT's propriatary syntax alike style  8)

And for me it envolves extra effort to remember the syntax to use it, i think i will keep using my own API encapsulation ;)

...   
Title: Re: PB9 and Objects
Post by: James C. Fuller on August 23, 2008, 01:07:04 PM
Quote from: José Roca on August 23, 2008, 06:42:41 AM

Quote
Maybe it's just me but why do new commands seem to take the form of STATEMENT VERB PARAMETER TO RESULT, I guess like the DDT functions do. It seems overly verbose. I mean GLOBALMEM ALLOC count TO vHndl. Okay, it works but vHndl = MEMALLOC(count) seems better at least in my opinionated eyes today.

I always have disliked the use of statements instead of functions, mainly because you always have to use a variable for the result, e.g. you can't use IF MemAlloc(count)  = 0 THEN...


I've decided to use MACROS

James




#COMPILE EXE
#DIM ALL

MACRO FUNCTION ClipGetText()
    MACROTEMP s
    DIM s AS STRING
    CLIPBOARD GET TEXT TO s$
END MACRO = s$
MACRO FUNCTION ClipSetText(Param)
    MACROTEMP i
    DIM i AS LONG
    CLIPBOARD SET TEXT Param TO i
END MACRO = i
FUNCTION PBMAIN () AS LONG

    LOCAL S1,S2 AS STRING
    LOCAL RetVal AS LONG
   
    S1 = "James Fuller"


    IF ClipSetText(S1) THEN
        ?"No ReVal"
    END IF

    S2 = ClipGetText
    ?"S2 = ";S2
   
    WAITKEY$
END FUNCTION
Title: Re: PB9 and Objects
Post by: Patrice Terrier on August 23, 2008, 02:19:24 PM
The use of MACRO enlarge the size of the resulting EXE, while a true function won't.


FUNCTION ClipGetText()
    LOCAL s AS STRING
    CLIPBOARD GET TEXT TO s
    FUNCTION = s
END FUNCTION


...
Title: Re: PB9 and Objects
Post by: James C. Fuller on August 23, 2008, 04:27:23 PM
Quote from: Patrice Terrier on August 23, 2008, 02:19:24 PM
The use of MACRO enlarge the size of the resulting EXE, while a true function won't.


FUNCTION ClipGetText()
    LOCAL s AS STRING
    CLIPBOARD GET TEXT TO s
    FUNCTION = s
END FUNCTION


...

????
Macro = No stack frame which is 1 meg and  function call = slower

James
Title: Re: PB9 and Objects
Post by: Patrice Terrier on August 23, 2008, 06:44:58 PM
Macro produces largest code when you use it as a replacement for standard subroutines or functions.
Because instead of having the subroutine or function only once in your code, you have it each time the macro code substitution is being done, and if you use this macro say 20 times in your code then you will see the difference in the resulting EXE size.


For example try these two examples based on your code, and tell me which one produces the smallest code size

1 - Using MACRO

MACRO FUNCTION ClipGetText()
    MACROTEMP s
    DIM s AS STRING
    CLIPBOARD GET TEXT TO s$
END MACRO = s$
MACRO FUNCTION ClipSetText(Param)
    MACROTEMP i
    DIM i AS LONG
    CLIPBOARD SET TEXT Param TO i
END MACRO = i
FUNCTION PBMAIN () AS LONG

    LOCAL S1,S2 AS STRING
    LOCAL RetVal AS LONG
   
    S1 = "James Fuller"


    IF ClipSetText(S1) THEN
        ?"No ReVal"
    END IF

    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    ?"S2 = ";S2
   
    WAITKEY$
END FUNCTION


2 - Using standard function

FUNCTION ClipGetText() AS STRING
    LOCAL s AS STRING
    CLIPBOARD GET TEXT TO s
    FUNCTION = s
END FUNCTION
FUNCTION ClipSetText(BYVAL sParam AS STRING) AS LONG
    LOCAL i AS LONG
    CLIPBOARD SET TEXT sParam TO i
    FUNCTION = i
END FUNCTION
FUNCTION PBMAIN () AS LONG

    LOCAL S1,S2 AS STRING
    LOCAL RetVal AS LONG
   
    S1 = "James Fuller"


    IF ClipSetText(S1) THEN
        ?"No ReVal"
    END IF

    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    ?"S2 = ";S2
   
    WAITKEY$
END FUNCTION

Title: Re: PB9 and Objects
Post by: Edwin Knoppert on August 23, 2008, 06:48:33 PM
They often forget that these calls are also functions.
So reducing one wrapper function isn't gonna help much..
Title: Re: PB9 and Objects
Post by: James C. Fuller on August 23, 2008, 07:18:56 PM
You're right of course Patrice!!
My brain was polluted this morning working with Visual Basic 2008 Express Edition trying to get a PB COM server working with it. Duh....

James
Title: Re: PB9 and Objects
Post by: Bob Zale on August 24, 2008, 09:33:43 AM
"Macro = No stack frame which is 1 meg and  function call = slower"


Functions can't possibly have a 1 MEG stack frame.  The physical limit is 64K as the extreme maximum, typically much, much less (like tens or hundreds of bytes).  You're probably thinking of a THREAD stack frame.

Best regards,

Bob Zale
PowerBASIC Inc.

Title: Re: PB9 and Objects
Post by: James C. Fuller on August 24, 2008, 12:06:20 PM
Quote from: Bob Zale on August 24, 2008, 09:33:43 AM
"Macro = No stack frame which is 1 meg and  function call = slower"


Functions can't possibly have a 1 MEG stack frame.  The physical limit is 64K as the extreme maximum, typically much, much less (like tens or hundreds of bytes).  You're probably thinking of a THREAD stack frame.

Best regards,

Bob Zale
PowerBASIC Inc.



No I got it from here??


http://www.powerbasic.com/support/help/pbwin/index.htm

James



Title: Re: PB9 and Objects
Post by: Bob Zale on August 24, 2008, 12:18:12 PM
Each time a THREAD is created, a stack section (default=1M) is allocated for all functions/methods to use.  No new stack memory is allocated for each function/method invocation.

Bob
Title: Re: PB9 and Objects
Post by: Edwin Knoppert on August 24, 2008, 12:30:50 PM
Question is if a BASIC programmer should worrie about details on that a level.
I don't.. just like the register stuff.

Like a said, a call to Instr() or Mid$() are functions too, 'overhead' any way.
You would gain only one wrapper, your custom function.
So what's the point.. unless you write all code in assembly.
Title: Re: PB9 and Objects
Post by: James C. Fuller on August 24, 2008, 12:50:31 PM
Quote from: Edwin Knoppert on August 24, 2008, 12:30:50 PM

Like a said, a call to Instr() or Mid$() are functions too, 'overhead' any way.

Not necessarily true and probably not. There is no need for a full stack frame on internal calls.

James
Title: Re: PB9 and Objects
Post by: Edwin Knoppert on August 24, 2008, 01:05:32 PM
I already thought i would get this response, what about your function calling another custom procedure?

It's really a nonsense discussion.
Maybe suitable for rocket sience..
Title: Re: PB9 and Objects
Post by: Theo Gottwald on August 24, 2008, 09:21:59 PM
The time, the final API Call for the clipboard uses is much longer, then the MACRO or the Function at that place.

And alltogether, there is not even in phantasie a scenario thinkable in which any of these timedifferences would play any role hehehe.
At least not for the Clipboard call.

Even in very high time-critical situations, the calling of a PB Sub or Function is not a problem and can even be an advantage because of the use and new Assignement of REGISTER Variables.

MACROS are in theory faster, but it really depends on the situation, because the CPU caching (strategy?) and the REGISTER usage plays a role.

In the situation with the Clipboard from before, none of all these aspects is of any real Usage, because we don't need to read or set the Clipboard >100.000 times each seconds.
Or did I miss something here :-).
Title: Re: PB9 and Objects
Post by: Paul Squires on August 24, 2008, 10:36:03 PM
Macro? Function? blah blah blah.... none of that is important because I JUST GOT MY PB9 !!!!  :D

I'll be tucked away for a week playing with this thing. Sweeeeeeeeeeet!

Title: Re: PB9 and Objects
Post by: Bob Zale on August 25, 2008, 01:22:36 PM
I believe that calls for a Woo-Hoo!   Ok, so I'm just a tiny bit biased...  {smile}  Thanks for kind words and the excitement.

Bob Zale
PowerBASIC Inc.
Title: Re: PB9 and Objects
Post by: Theo Gottwald on August 26, 2008, 07:48:54 PM
I I'd also like just to get a nice house or a farm on the countryside,
have a computer, the new PB 9, a whirlpool - somebody who looks for alldays work ....

And then do a some month not much more then just enhance all my old ( old is everything before PB 9 :-) ) Code with the new possibilities.

But we'll see when it can happen.


Title: Re: PB9 and Objects
Post by: Paul Squires on August 26, 2008, 10:41:07 PM
Theo, good point - I wish also that I could update all of my old code. I thought about a couple of them last night but I think that I am not going to bother. I'll use PB9 in my next project rather than try to retrofit it into my old code. There's never a shortage of new projects!  :)

Maybe I'll win the lottery and then be able to program full time!
Title: Re: PB9 and Objects
Post by: José Roca on August 26, 2008, 11:06:43 PM
 
Apparently, I'm one of the few that are using the new COM support for COM programming instead of OOP :)
Title: Re: PB9 and Objects
Post by: Paul Squires on August 27, 2008, 02:08:00 PM
:)  I'll have a HUGE need for COM in my next programming project. It will involve a lot of Word, Excel and Outlook manipulation.... but, for now, I'll be using COM for OOP. Baby steps for me. My brain can only handle so much.

;D

Title: Re: PB9 and Objects
Post by: José Roca on August 27, 2008, 02:16:47 PM
 
To save you some head scratching, don't try to use EXCEL with direct calls; use OBJECT GET/CALL... Although EXCEL's type library lists dual interfaces, they return pointers to the dispatch interfaces, so trying to use them will end in frustration and GPFs.

Title: Re: PB9 and Objects
Post by: Paul Breen on August 27, 2008, 08:16:07 PM
Jose says he is doing com without oop and the new pb9 has oop that is com. I know that there is oop without com in other languages but I would like some clarification about the new pb9 oop. Is the new implementation of objects in pb9 exclusively com technology that is packaged in a clever way?
Is all of oop in powerbasic just com in a easy to use syntax? Does this mean that there is some advantage of oop that is not in the new compiler because of how it was implemented? Even strong advocates of oop like the inventor of python think that multiple inheritance causes more trouble than it solves so I am not looking for something like that.

I am attracted to the idea that powerbasic has used a proven "off the shelf" technology from Microsoft if I have the right understanding. Do I?
Title: Re: PB9 and Objects
Post by: José Roca on August 27, 2008, 08:50:18 PM
 
Quote
Is the new implementation of objects in pb9 exclusively  com technology that is packaged in a clever way?

You bet.

Quote
Does this mean that there is some advantage of oop that is not in the new compiler because of how it was implemented?

Sure, but why everybody is talking about OOP and don't pay attention to what is for me more important and powerful, like the ability to use and write low-level COM servers? Can you use DirectX 9 with VB6?

Quote
Even strong advocates of oop like the inventor of python think that multiple inheritance causes more trouble than it solves so I am not looking for something like that.

Using COM classes you get clean and reusable objects that are self contained. Using multiple inheritance, you get MFC  ;)