On Tue, 06 Jan 2009, Teo Fonrouge wrote: Hi Teo,
> I'm building an Client/Server database library based on Harbour Objects, the > idea behind this is simple: > * On the Server side: > - An RDOServer object is created and starts listening for incoming clients > on a predetermined port, when an new client connect request is received, then > an Harbour Thread is fired and it polls for the client requests, tipically > the client will start the comunication with a TTable():New(). This Thread > will serve to the client for all the TTable objects required and process the > messages and then return to the client the result (as an serialized HB_ITEM). > * On the Client side: > - An TTable object is created *and if* his tablename is something > like "RDO://rdoserver.com:port/the_database_name.dbf", this will instantiate > an RDOCLient object and assign it to a data in the TTable object. The new > TTable object requested (in the "NEW" message) will be sended to the Server > (as an string with an classname id and serialized params) where the TTable > object will be created and then returned to the client (as an serialized > Object item) where it will be the assigned as the actual client TTable > object. Some of the TTable object messages/methods will be processed on the > server and the result returned to the client, i.e. when the database is > needed to be physically opened ( Table:Open() ) the "Open" method on the > Client will send the request to the Server where the "Open" method will be > executed, the result is returned to the client. > * Remarks > - TTable Class is part the opensource wxHarbour library > (http://sourceforge.net/projects/wxharbour/) > - Both the Client and the Server class definitions are exactly equal, > they > differ only when an Client request TTable is needed. > - Sorry for my bad english. > > * The Help I request: > - I need to be able to bypass the scope class checking when an method > needs to be executed on the Server side (check the function > TRDOSOCKETBASE_PROCESSCLIENTREQUESTS on the attached cpp source code). > Currently I cannot execute the private/protected methods on the Server side > and this messages/methods need to be executed *as if* they were executed on > the Client. Please check this function on the attached source code. The class scoping is not only protection against executing methods from external code. It's also used to chose valid method when nameconflict appears. It's possible to disable scoping but in such way you will also lost real private/hidden messages. F.e. this code perfectly well works in Harbour though two classes uses hidden instance variable with the same name: 'v'. Harbour uses scopes to resolve name conflicts. #include "hbclass.ch" create class cls1 var v init 0 hidden exported: method inc inline ++::v endclass create class cls2 from cls1 var v hidden exported: method touch inline ::v := seconds() method last inline ::v endclass proc main() local o := cls2():new() ? o:inc() ? o:last() wait o:touch() ? o:inc() ? o:last() wait o:touch() ? o:inc() ? o:last() wait return If you disable scoping then this code will not longer work. Just simply the same code: ::v is used to access two different instance variables and the valid one is chosen using the class of method which executes it. Please also note that such protection is very important when you are working on bigger project in a team. You do not have to worry that name conflicts in subclasses written by other developers will break your code. It also eliminates possible mistakes and incorrect assigning hidden data of other classes. > Any help, insight, criticism are welcome in this order, no, just kidding :), > please provide any help, idea or whatever. It's not clear for me why you want to execute hidden or protected messages from external code. If someone defines some messages with restrict scope then he usually intentionally want to protect them against unauthorized access. If scoping breaks some functionality necessary for external code then class definition should be changed otherwise the scoping is reduce to source code decoration. > PD: I have checked the hb_dbgObjSendMessagge() (classes.c) and it seems that > it does what I want, but I'm a little lost in understand the details. Yes, it does. It's helper function for debugger which allow to execute messages setting execution context (scope) to given HVM stack frame. In debugger iProcLevel parameter is used to set the same scope as for the .prg code which is currently debugged. If it's 0 then scope is set like for methods of pObject so you can execute any hidden methods defined in pObject class but it's not enough to execute hidden messages defined in parent classes. This is not intentional but result of my typo and I'll change it because now it does not make what I defined that it should. The line 2420: pBase->item.asSymbol.stackstate->uiClass = uiClass; should be changed to: pBase->item.asSymbol.stackstate->uiClass = pMethod->uiSprClass; The iParamOffset is an offset to parameters in current function frame. To use this function you have define function visible for .prg code and call it instead of directly sending messages. In debugger __DBGSENDMSG() is used for it. You can create your own functions with such functionality, f.e.: HB_FUNC( __MYSENDMSG ) { PHB_ITEM pObject = hb_param( 1, HB_IT_ANY ); PHB_ITEM pMessage = hb_param( 2, HB_IT_SYBOL | HB_IT_STRING ); hb_dbgObjSendMessage( 0, pObject, pMessage, 3 ); } and in your C code call this (pass parameters to HVM stack and execute hb_vmDo( 2 + <n> ) ) instead of sending messages directly to pObject, f.e.: static PHB_DYNS s___mySendMsg = NULL; [...] if( s___mySendMsg == NULL ) hb_dynsymGetCase( "__MYSENDMSG" ); hb_vmPushDynSym( s___mySendMsg ); hb_vmPushNil(); hb_vmPush( pMessage ); hb_vmPush( pObject ); for( ui = 0; ui < uiPCount; ++ui ) hb_vmPush( pParam[ ui ] ); hb_vmDo( uiPCount + 2 ); The intermediate function is necessary to create frame where we can set valid execution context (scope). __MYSENDMSG should be visible for HVM (hb_dynsymFind()) so it should be REQUEST-ed in your .prg code. It will work but this method disables automatic name conflict resolving so if you have hidden methods using same name defined in different subclasses then you will execute only and always the last one. In the above example you will access 'v' from cls2 but you will not be able to access 'v' from cls1. For your own use it maybe enough but the above should not be used as documented Harbour method in some generic code. It's programmer job to properly define class members scopes to not create any of such hacks in upper level code which uses objects of given class. best regards, Przemek _______________________________________________ Harbour mailing list Harbour@harbour-project.org http://lists.harbour-project.org/mailman/listinfo/harbour