It is currently Tue Jul 17, 2018 10:35 am

All times are UTC + 1 hour




Post new topic Reply to topic  [ 21 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Macro framework for creating COM objects
PostPosted: Sun Jun 04, 2006 5:23 pm 
Offline
PureBasic Team
PureBasic Team
User avatar

Joined: Fri Apr 25, 2003 5:21 pm
Posts: 5763
Location: Germany
With the introduction of interfaces in PureBasic, accessing external COM (Component Object Model) objects
has become fairly simple (in terms of needed amounts code to do so). However, creating COM objects in PB
to be used externally, or with API commands is still something that requires lots of knowledge about PB and
COM and quite some work to do. This framework tries to change that. It provides a set of macros to easily define
an object and also to automate most of the tasks common to all object implementations (like implementing the
IUnknown interface). Additionally, it provides extensive debugging functionality to track down bugs in your

implementation. There are also some macros that are useful for general COM development.

Feature list
Code:
General

 - No preprocessing needed. Evetything is pure PB code.
 - Everything contained in residents and includefiles, minimizing possible problems with future PB versions
 - Threadsafe and unicode ready
 - Works with the EnableExplicit compiler option

Object implementation

 - Simple macros to define the class structure
 - Multiple interfaces supported in one class (up to 9)
 - Implementation of IUnknown is completly done by the framework
 - Constructor/Destructor support
 - For not-implemented methods, a default method is automatically inserted which returns #E_NOTIMPL
 - A VTable is created with a single macro call
 - Macros for easy definition and handling of GUID values (IID, CLSID, ...)

Debugging

 - Complete tracking of all calls to the objects methods, including displaying return values
 - Tracking of calls to dead (allready freed) objects
 - Catching of method calls outside the VTable (to find calls to wrong interfaces)
 - The amout of debug output for the tracking can be customized with 'DebugLevel'
 - Conversion of GUID and HRESULT values to text for easier debugging
 - With Debugger off, the debug output is printed with OutputDebugString_() for easy dll debugging


This framework is intended for those that have allready some understanding
of how COM works, but want to make their life easier when it comes
to creating objects with PB.

NOTE: The purpose of this framework is to implement interfaces that are defined in the Microsoft Component
Object Model. The intend is not to provide general OOP functionality for PureBasic. To automate most
of the work, the framework needs information on the given interfaces, this is why only predefined interfaces
can be implemented, not any custom one. (currently 855 interfaces are known to the framework)

I started this project to ease my own work with COM in PureBasic, and
also als a challange to see how far i could go with the PB4 macro capabilities.
As this shows, there is quite a lot that can be done with it. It also prooves
that you can produce totally ugly code with them.
(have a look at the main includefiles and you will see. Better don't try to understand
how all of it works ;))

As an Example, implementing a basic IBindStatusCallback interface to be used
with UrlDownloadToFile_() can be as simple as this:
Code:
COMClass(StatusObject)
  COMInterface(StatusObject, IBindStatusCallback)
 
  COMConstructor(StatusObject)
    COMConstructorReturn IBindStatusCallback
  EndCOMConstructor 

EndCOMClass(StatusObject, IBindStatusCallback)

Procedure StatusObject_IBindStatusCallback_OnProgress(*THIS.StatusObject, Progress.l, ProgressMax.l, StatusCode.l, szStatusText.l) COMMethodOf(StatusObject)
  Protected percent.f

  If ProgressMax = 0
    percent.f = 0
  Else
    percent.f = (Progress*100)/ProgressMax
  EndIf
   
  Debug Str(Progress)+"/"+Str(ProgressMax)+"  ("+StrF(percent, 1)+"%)"

  ProcedureReturn #S_OK
EndProcedure

BuildCOMVTable_IBindStatusCallback(StatusObject)

RemoteName$ = InputRequester("File Download:", "Enter remote FileName: ", "http://www.purebasic.com/")
If RemoteName$ = "": End: EndIf

LocalName$ = SaveFileRequester("Select Local Filename:", "C:\temp.html", "All Files|*.*", 1)
If LocalName$ = "": End: EndIf


BindStatus.IBindStatusCallback = New_StatusObject()

Debug "Starting download..."
If URLDownloadToFile_(0, @RemoteName$, @LocalName$, 0, BindStatus) = #S_OK
  Debug "Download successful."
Else
  Debug "Download failed."
EndIf

BindStatus\Release()

End


Here is the download link. Make sure you have a look in the Readme file on how it all works.
There are also some example codes included.
To install it, just extract the archive directly into the purebasic folder.
(it adds a 'ComFramework' subfolder and 2 resident files, nothing more)

http://freak.purearea.net/tools/ComFramework.zip

I'll be glad to hear any comments or bugreports.

_________________
quidquid Latine dictum sit altum videtur


Top
 Profile  
Reply with quote  
 Post subject: Re: Macro framework for creating COM objects
PostPosted: Sun Jun 04, 2006 6:17 pm 
Offline
PureBasic Expert
PureBasic Expert
User avatar

Joined: Sun Apr 27, 2003 4:41 pm
Posts: 1661
Location: Germany
OMG this must be the ugliest yet at the same time the nicest PB-code I've ever seen. Great, great work!

sorry for being the first to reply ;)

_________________
Good programmers don't comment their code. It was hard to write, should be hard to read.


Last edited by traumatic on Sun Jun 04, 2006 9:07 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Jun 04, 2006 6:25 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Fri Apr 25, 2003 7:44 pm
Posts: 465
Location: end of www
Damn ... didnt test it yet (time) but the feature list sounds tremendous :!:

Thanks, fr34k 8)

_________________
regards,
benny!
-
pe0ple ar3 str4nge!!!


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Jun 04, 2006 6:27 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Thu Sep 16, 2004 9:50 pm
Posts: 658
Location: France
Thanks :D

_________________
DroopyLib/PBFastLib/HMod


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Jun 04, 2006 9:11 pm 
Offline
Enthusiast
Enthusiast

Joined: Sat Dec 20, 2003 6:19 pm
Posts: 468
Location: Switzerland
Krass :shock:

_________________
Athlon64 3700+, 1024MB Ram, Radeon X1600


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Jun 04, 2006 10:20 pm 
Offline
Enthusiast
Enthusiast

Joined: Fri Jun 06, 2003 2:41 pm
Posts: 169
Location: Belgium
VERY COOL !!! 8)

Thanks for sharing :D


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Jun 04, 2006 10:27 pm 
Offline
PureBasic Fanatic
PureBasic Fanatic

Joined: Fri Dec 09, 2005 12:15 pm
Posts: 2236
Location: Elbonia
Thanks! BTW, how much did it take to code all the includes? :shock: . Very nice work :D .

_________________
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)


Top
 Profile  
Reply with quote  
 Post subject: Re: Macro framework for creating COM objects
PostPosted: Mon Jun 05, 2006 12:06 am 
Offline
Addict
Addict

Joined: Mon May 29, 2006 1:01 am
Posts: 1965
Location: Outback
freak wrote:
It also prooves that you can produce totally ugly code with them.

:D

Thanks Freak. :)


Edit: This is huge! :shock: Big work, thank you for sharing!

_________________
Dare2 cut down to size


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Jun 05, 2006 12:19 am 
Offline
Always Here
Always Here
User avatar

Joined: Thu Jun 24, 2004 2:44 pm
Posts: 5739
Location: Berlin - Germany
thx freak, nice work :!:

_________________
PureBasic 5.70 | SpiderBasic 2.10 | Windows 10 Pro (x64) | Linux Mint 19.0 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Jun 05, 2006 12:51 pm 
Offline
PureBasic Team
PureBasic Team
User avatar

Joined: Fri Apr 25, 2003 5:21 pm
Posts: 5763
Location: Germany
thanks everyone.

> BTW, how much did it take to code all the includes?

Only the two main ones (BaseInclude.pb / Debugging.pb) are hand coded. The rest is
generated from PB's interface list and my own guid list that i generated a while ago.

btw, even for those who only want to access external COM objects, the 'GuidList.res'
file in the framework might be intresting.
It is independent from the rest, and contains the 'DefineKnownGUID/IID/CLSID()' macros only.
They can be used to easily define those needed IID/CLSID values without the need to look them up.
Just like this:
Code:
DefineKnownIID(IID_IDispatch)

; now it is accessible like this:
;
a = ?IID_IDispatch

_________________
quidquid Latine dictum sit altum videtur


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri Nov 24, 2006 2:20 am 
Offline
PureBasic Team
PureBasic Team
User avatar

Joined: Fri Apr 25, 2003 5:21 pm
Posts: 5763
Location: Germany
Are any of you people making use of this framework ? I am just curious :)

Well, to anyone who uses this it, i have a new procedure which i find very helpfull for debugging:

The procedure displays all the interfaces that a given (foreign/unknown) object supports
trough its QueryInterface() method. (It checks all the interfaces known by the framework.)

It may surprise you how much stuff is actually supported by various objects.
Try this with a IWebBrowser2 or IHTMLDocument2 pointer from a webgadget
for example... there is much stuff available there. ;)

You can use the code as it is, or copy the procedure to the end of "Debugging.pb" in the framework,
then it is available always when you use "EnableCOMDebugging".

Note: as with the other debugging functions of the framework, the included guid list
is very big, so this is not meant for the final executable, but only for testing/debugging.

Here is the procedure + a short example:
Code:
; this is important so the GuidList is included
EnableCOMDebugging

Procedure DisplaySupportedInterfaces(This.IUnknown)
  Protected index, StoredName$, New.IUnknown
  Restore __COM_DEBUG_GUIDNames
 
  For index = 1 To #__COM_DEBUG_GUIDCount
    Read StoredName$
    If Left(StoredName$, 4) = "IID_"
      If This\QueryInterface(?__COM_DEBUG_GUIDValues + (index-1)*SizeOf(GUID), @New.IUnknown) = #S_OK
        New\Release() ; very important!
        New = 0       
        __COM_DEBUG("Object supports: " + Right(StoredName$, Len(StoredName$)-4))
      EndIf
    EndIf   
  Next index
EndProcedure

; ---------------- Example code: Lets check the AutoComplete object --------------------

DefineKnownCLSID(CLSID_AutoComplete)
DefineKnownIID(IID_IAutoComplete)

; This is only needed for the CoCreateInstance_(), its not needed for the above procedure
CoInitialize_(0)

; create autocomplete object
If CoCreateInstance_(?CLSID_AutoComplete, 0, 1, ?IID_IAutoComplete, @AutoComplete.IAutoComplete) = #S_OK

  ; check what is supported
  DisplaySupportedInterfaces(AutoComplete)
 
  ; release again
  AutoComplete\Release()
EndIf

CoUninitialize_()

_________________
quidquid Latine dictum sit altum videtur


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri Nov 24, 2006 12:23 pm 
Offline
Enthusiast
Enthusiast

Joined: Fri Jun 06, 2003 2:41 pm
Posts: 169
Location: Belgium
@Freak
Could you give some more examples ?
Is it possible to use this framework to create an addon for msword?
Or to call msword macros ?

Thanks.

_________________

LuckyLuke


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Nov 26, 2006 5:05 pm 
Offline
PureBasic Team
PureBasic Team
User avatar

Joined: Fri Apr 25, 2003 5:21 pm
Posts: 5763
Location: Germany
LuckyLuke wrote:
@Freak
Could you give some more examples ?
Is it possible to use this framework to create an addon for msword?
Or to call msword macros ?

Thanks.


Well, its hard to give simple examples for that. Did you look at the included ones ?
You probably can access msword stuff, but i imagine it will be some work to
get that done.

_________________
quidquid Latine dictum sit altum videtur


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed Feb 28, 2007 8:06 pm 
Offline
Addict
Addict
User avatar

Joined: Thu Jul 01, 2004 2:51 am
Posts: 898
Location: Tacoma, WA
freak,

I downloaded this and browsed around a bit. I noticed the AsyncXXXXXXX.pb files in the ComFramework/Interfaces directory. Are those for activesync?


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Mar 01, 2007 12:10 am 
Offline
Addict
Addict
User avatar

Joined: Thu Jul 01, 2004 2:51 am
Posts: 898
Location: Tacoma, WA
A couple seconds after posting that I knew the answer was 'no'. So... do you have any tips on how I could possibly get started with working with ActiveSync? To sync contacts between outlook contacts on the Windows Mobile device and the desktop PC.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 21 posts ]  Go to page 1, 2  Next

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 6 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye