OPB v0.56 (objective PB)

Applications, Games, Tools, User libs and useful stuff coded in PureBasic
User avatar
idle
Always Here
Always Here
Posts: 5839
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

OPB v0.56 (objective PB)

Post by idle »

OPB is a object orientated runtime framework, similar to working with regular PB objects

source http://www.idlearts.com/OPB.zip
Linux, Windows and partial support on mac

supports
collections of classes (modules)
inheritance
Class data container to set & get additional properties or arbitrary data
memory managed and garbage collected
Runtime FFI (Foreign Function Interface) call supporting standard and cdecl VarArgs (x86 only)

external to the runtimes library is OPBWindow an event driven window manager, currently only linux and windows

a opb class function takes this form

Code: Select all

ProcedureDLL ClassVector2DScale(*this.ClassVector2D,sX.f,sY.f)
 *this\x* sx
 *this\y * sy 
  ProcedureReturn *this 
 EndProcedure
Classes can be inherited by using extends on a structure or you can include another class by
providing a pointer in the class structure and then create a new instance of it in your constructor
OPB is also compatible with Interfaces should you wish to present classes via them.

An example of how you define a class

Code: Select all

    
;Define the class structure      
Structure ClassVector2D 
  x.f
  y.f
  length.f
  normal.f
EndStructure  

;Create Destructor 
ProcedureDLL ClassVector2D_Free(*class.Vector2D)
  OPBFreeClass(*class)
EndProcedure

;Create a Class Construtor for ClassVector2D  
ProcedureDLL NewClassVector2D(Module,name.s,x.f,y.f)
  Protected *this.ClassVector2D                                                                                                          
   
  ;Create a new class instance   
 *this = OPBNewClass(Module,name,SizeOf(ClassVector2D),@ClassVector2D_Free())     
  If *vec2D 
    ;Initilize vars 
    If x Or y
     *vec2D\length = Sqr( x * x + y * y)
     *vec2D\normal = 1 / *vec2D\length
     *vec2D\x = x  * *vec2D\normal
     *vec2D\y = y * *vec2D\normal 
    EndIf 
    ProcedureReturn *vec2D
  EndIf 
EndProcedure 

ProcedureDLL.f ClassVector2D_GetX(*this.ClassVector2D) 
   ProcedureReturn *this\x * *this\length     
EndProcedure  

ProcedureDLL.f ClassVector2D_GetY(*this.ClassVector2D)
   ProcedureReturn *this\y * *this\length      
EndProcedure

ProcedureDLL.f ClassVector2D_Magnitude(*this.ClassVector2D)
  ProcedureReturn *this\length 
EndProcedure 
 
;... 

OPBWindow
OPBWindow is a demo of a cross platform event driven windows manager
providing a means to have multiple windows running including a window screen

Events are registered with a precedence
1 a specific gadget and event "OnClick" ...
2 a specific gadget or any gadget and all its events via "Onevent"
1 a specific window and event "OnWindowMaximize"
2 a specific window or any window and all its gadgets events via "OnEvent"
1 a windowScreen event

The keyboard functions replace pb functions(**don't use initkeyboard**)
and is mapped to US English keyboard including lower case keys

To test an arbitary key where you need to know multiple keys
OPB_Window_KeyboardPressed(window,#OPBKey_UP)
OPB_Window_KeyboardReleased(window,#OPBKey_DOWN)
To get a the current key
key = OPB_Window_GetKey(window)
keyString = OPB_Window_GetKeyString(key) ;convert it to string

Code: Select all

;start the opb window manager passing in a module and name of app
If OPB_Window_Manager(OPBStart(),"myapp")
 
 InitSprite()
 
  ;create a new window  
  w1 = OPB_Window(#PB_Any,0,0,800,600,"Window1", #PB_Window_ScreenCentered | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget |#PB_Window_SizeGadget) 
  ;open a screen on the window
  OPB_Window_Screen(w1,0,25,800,575,0,0,0)
  ;register the screen drawing function
  OPB_Window_AddEvent(w1,#Null,#ScreenCallBack,@window1_screen());register some specific window events 
  OPB_Window_AddEvent(w1,#Null,#OnWindowMaximize,@Window1_OnWindowMaximized())
  OPB_Window_AddEvent(w1,#Null,#OnWindowMinimize,@Window1_OnWindowMinimized())
  ;Register a catch all for events  
  OPB_Window_AddEvent(w1,#Null,#OnEvent,@Window1_OnEvent())
  ;add a button and set default event and it's callback 
  b1 = OPB_Window_AddGadget(w1,ButtonGadget(#PB_Any,5,5,60,20,"OK"),#OnClick,@Window1_OK_OnClick())
  
  ;create a second window 
  w2 = OPB_Window(#PB_Any,0,0,300,200,"Window2",#PB_Window_ScreenCentered | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget |#PB_Window_SizeGadget)   
  ;get it's native pb number
  ;add a menu 
  If CreateMenu(0,WindowID(w2))
    MenuTitle("Project")
    MenuItem(1, "Open")
    MenuBar()                  
    MenuItem(4, "Close")
  EndIf
  ;register the menu callcack
  OPB_Window_AddEvent(w2,#Null,#OnMenu,@Window2_OnMenu())
  ;Add a button and register it's default event 
  b2 = OPB_Window_AddGadget(w2,ButtonGadget(#PB_Any,235,5,60,20,"OK"), #OnClick,@Window2_OK_OnClick())
  ;additionally add mouse enter and leave and scroll events for the button 
  OPB_Window_AddEvent(w2,b2,#OnMouseEnter,@Window2_OK_OnMouseEnter())
  OPB_Window_AddEvent(w2,b2,#OnMouseLeave,@Window2_OK_OnMouseLeave())
  OPB_Window_AddEvent(w2,b2,#OnMouseScroll,@Window2_OK_ONMouseScroll())
  
  ;Create a listview and add an OnEvent callback for the Gadget 
  lv2 = ListViewGadget(#PB_Any,5,30,290,130) ;
  OPB_Window_AddGadget(w2,lv2,#OnEvent,@Window2_LV2_OnEvent()) 
  
  ;enter the main loop 
  OPB_Window_Main()
  
  OPBStop()
  ;if used from the OPB dll call need to call opbclose()
  ;OPBClose()
EndIf
OPBFFI (code nicked from wilbert)
The FFI may be useful in situations where you want to add a runtime plugin mechanism
a scripting environment or test bed or just need to call functions with VarArgs foo(int a,int b,...)

Code: Select all

mlib = OPB_FFI_OpenLibrary(file,@enumfuncs())

;make a wrapper function to call the library function
Procedure.f Foof(a.f,b.f)
  Static fn   
  If Not fn    ;get the function and set the number of parameters 
    fn = OPB_FFI_GetFunction(mlib,"foof",2) 
  EndIf   
  If fn
    OPB_FFI_PushF(fn,a)   ;push parameters using the type functions  
    OPB_FFI_PushF(fn,b)
    ProcedureReturn OPB_FFI_CallF(fn)   ;call the function via the required return type 
  EndIf   
EndProcedure 
Last edited by idle on Fri Mar 16, 2012 5:53 am, edited 18 times in total.
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Re: OPB v0.2 (objective PB)

Post by ts-soft »

Interesting thing Image
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
User avatar
luis
Addict
Addict
Posts: 3893
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: OPB v0.2 (objective PB)

Post by luis »

I tinkered with this idea myself some time ago, but never tried it out fully.

I was afraid it would ended up being too slow...

I'll look into your example, seems better of what I had in mind... thanks for sharing it Idle :)
"Have you tried turning it off and on again ?"
A little PureBasic review
User avatar
idle
Always Here
Always Here
Posts: 5839
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: OPB v0.2 (objective PB)

Post by idle »

Thanks for the comments guys.

The problem as I see it is more to do with how to make it fast enough while keeping the syntax simple to use
and still maintaining sufficient encapsulation.

edit:
I checked if multiple class inheritance is working and I've replaced the silly set and gets functions with Sel Macros
That way it stays as pointer to pointer dereference which isn't really that different from static binding.

So each class function has a pointer to its members and pointers to an opbVariable

you set the *var = *members\foo

and then use a Sel Macro to dereference the vars type or you could of course ignore the macro and *var\value\opbFloat
selFloat(*var) = x

Code: Select all

Procedure ClassVector2DTranslate(class,TX.f,Ty.f)
   Protected *members.classVector2DMembers, *varX.opbVariable,*varY.opbVariable
  *members = OPBGetMembers(ModMath,class) 
  If *members
    *varX = *members\myFloatX
    *varY = *members\myFloatY
     SelFloat(*varX) + tx 
     SelFloat(*varY) + ty 
  EndIf  
EndProcedure 
posted v0.3
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
idle
Always Here
Always Here
Posts: 5839
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: OPB v0.4 (objective PB)

Post by idle »

Removed the opaque pointers since it was near impossible to use PB objects
So now you just get the pointer to the members structure which is faster and enables you to use PB objects

so it looks like this now

Code: Select all

 Procedure ClassVector2DTranslate(class,TX.f,Ty.f)
  Protected *members.ClassVector2D
    *members = OPBGetMembers(ModMath,class) 
    If *members
     *members\myFloatX + tx
     *members\myFloatY + ty
    EndIf  
EndProcedure 


Changing it like this means that you need to have a destructor function for your class which is now
implemented as a macro before a NewClass function
This function isn't supposed to be called by the user, they call OPBFreeClass(module,class)
If they forget your destructor will be called by the garbage collector, though you need to supply the address
in the constructor

so you just call the default destructor macro and then pass the address as @_ClassStructureNameFree()

Code: Select all

 
OPBCreateDestructor(ModMath,ClassVector2D) 

Constructor Create a class construtor for ClassVector2D  
Procedure NewClassVector2D(name.s,x.f,y.f)
  Protected class,*members.ClassVector2D                                                               
  class= OPBNewClass(modMath,name,"Vector2D",SizeOf(ClassVector2D),@_ClassVector2DFree())     
  If class 
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
idle
Always Here
Always Here
Posts: 5839
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: OPB v0.5 (objective PB)

Post by idle »

Refined it a little more
I will try to get rid of the need to call OPBGetMembers(Module,class) in the next update
It only there for validation but it really it only tells you if it's a class and not necessarily the one requested
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
idle
Always Here
Always Here
Posts: 5839
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: OPB v0.51 (objective PB)

Post by idle »

got rid of the OPBGetMembers function, so no it's abstracted a little so it returns a pointer to an OPBClass struct
which contains the pointer to the users class structure and the index of the class in the module
if I didn't do it that way it would end up requiring a dynamic lookup.

So now Class procedures look very familiar

Code: Select all

ProcedureDLL.f ClassVector2DGetX(*vec2D.OPBCLass) 
  Protected *mv.ClassVector2D
  *mv = *vec2D\class  
  ProcedureReturn *mv\x * *mv\length     
EndProcedure  


Also added import, declares, openlibrary with prototype code generators, so you can dump copy and paste
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
fsw
Addict
Addict
Posts: 1603
Joined: Tue Apr 29, 2003 9:18 pm
Location: North by Northwest

Re: OPB v0.51 (objective PB)

Post by fsw »

Surely interesting stuff.
Because it's low level asm it's tight to 32bit OS.
Had to install PB32 in order to try it out...

Still very nice.
User avatar
idle
Always Here
Always Here
Posts: 5839
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: OPB v0.51 (objective PB)

Post by idle »

Ok I've quickly changed it to use maps and CRC32Fingerprint adding it to OPB52.pbi
It doesn't really require the use of the tries performance since it's producing a static late binding
originally it was using the tries to do run time look ups.

Also added in shared lib test so it spits out an Includefile for the dll.
the user just has to open the lib and get InitModule and call it with a value of 1 to generate the Include file
So if you wanted to make a dll out of a bunch of classes you include the classes file
and add two function InitModule() and CloseModule()

Feedback and suggestions would be appreciated regarding the use of it for libraries (ts-soft)
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
idle
Always Here
Always Here
Posts: 5839
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: OPB v0.53 (objective PB)

Post by idle »

Trimmed it down

So the basis of creating a class is now

Code: Select all

;Create the Classes Private Destructor 
Procedure _ClassVector2DFree(*members)
   ClearStructure(*members,ClassVector2D)
EndProcedure

;Create Classes Public Destructor 
ProcedureDLL ClassVector2DFree(Module,*class)
  OPBFreeClass(Module,*class)
EndProcedure

;Create a Class Construtor for ClassVector2D  
ProcedureDLL NewClassVector2D(Module,name.s,x.f,y.f)
  Protected *vec2D.ClassVector2D                                                                                                          
   
  ;Create a new class instance  ****Note pass the private destructor function eg @_ClassStuctureFree() 
 *vec2D = OPBNewClass(Module,name,"ClassVector2D",SizeOf(ClassVector2D),@_ClassVector2DFree())     
  If *vec2D 
    ;Initilize vars 
    If x Or y
     *vec2D\length = Sqr( x * x + y * y)
     *vec2D\normal = 1 / *vec2D\length
     *vec2D\x = x  * *vec2D\normal
     *vec2D\y = y * *vec2D\normal 
    EndIf 
    ;optional introspection 
    ProcedureReturn *vec2D
  EndIf 
EndProcedure 
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
idle
Always Here
Always Here
Posts: 5839
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: OPB v0.53 (objective PB)

Post by idle »

Added a quick example of an event driven window manager (not complete)

Code: Select all

XIncludeFile "classWindow.pbi"

;Test event driven windows

;define the event procedures for the window 1 gadgets 
Procedure w1OKOnClick() 
   Debug "w1 OK CLicked"   
 EndProcedure  
 
 ;define the event procedures for window 2 gadgets
 Procedure w2OKOnClick() 
   Debug "w2 OK CLicked"   
 EndProcedure  
 
 Procedure w2OKOnMouseEnter()
   Debug "w2 OK mouse enter"
 EndProcedure 
 
 Procedure w2OKOnMouseLeave()
   Debug "w2 OK Mouse leave"
 EndProcedure  

;create a new window add a button to it registering the event and address of the callbackl 
w1 = NewWindow("w1",0,0,300,200,"window1",#PB_Window_Normal) 
ClassWindowAddGadget(w1,ButtonGadget(#PB_Any,5,5,60,20,"OK"),#OnClick,@w1OKOnClick())

;create a second window add a button ...
w2 = NewWindow("w2",0,0,300,200,"window2",#PB_Window_Normal) 
tg = ClassWindowAddGadget(w2,ButtonGadget(#PB_Any,5,5,60,20,"OK"), #OnClick,@w2OKOnClick())
;additionally register "On mouse enter / On mouse leave" events to the button 
ClassWindowRegisterGadgetEvent(tg,#OnMouseEnter,@w2OKOnMouseEnter())
ClassWindowRegisterGadgetEvent(tg,#OnMouseLeave,@w2OKOnMouseLeave())

;enter the main loop 
ClassWindowMain()
;when the windows are closed it will free the memory 
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
fsw
Addict
Addict
Posts: 1603
Joined: Tue Apr 29, 2003 9:18 pm
Location: North by Northwest

Re: OPB v0.53 (objective PB)

Post by fsw »

Was wondering about the ProcedureDLL use in the include files, and the help file doesn't say anything what happens behind the curtain when ProcedureDLL is used in an EXE file (instead of a DLL).

The functions are not even exported... what a shame :P
User avatar
idle
Always Here
Always Here
Posts: 5839
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: OPB v0.53 (objective PB)

Post by idle »

No they're not exported from an exe but if you wanted to build a shared object / dll or static lib from your classes
it'd just be a pain to go back later through the source and declare them as procedureDll
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
fsw
Addict
Addict
Posts: 1603
Joined: Tue Apr 29, 2003 9:18 pm
Location: North by Northwest

Re: OPB v0.53 (objective PB)

Post by fsw »

Understood, thanks.

(And I thought you found a secret ingredient in the "PureBasic-Stew")
User avatar
idle
Always Here
Always Here
Posts: 5839
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: OPB v0.53 (objective PB)

Post by idle »

No stew there but might be possible to do it altering the asm, though I've never tried.
Windows 11, Manjaro, Raspberry Pi OS
Image
Post Reply