[GRASS-dev] [GRASS GIS] #2134: Create a general exit-safe interface to C libraries

GRASS GIS trac at osgeo.org
Fri Nov 22 08:53:52 PST 2013


#2134: Create a general exit-safe interface to C libraries
--------------------------------------------------+-------------------------
 Reporter:  wenzeslaus                            |       Owner:  grass-dev@…              
     Type:  enhancement                           |      Status:  new                      
 Priority:  normal                                |   Milestone:  7.0.0                    
Component:  Python ctypes                         |     Version:  svn-trunk                
 Keywords:  G_fatal_error, exit, multiprocessing  |    Platform:  All                      
      Cpu:  Unspecified                           |  
--------------------------------------------------+-------------------------

Comment(by wenzeslaus):

 Replying to [comment:10 huhabla]:
 > Replying to [comment:9 wenzeslaus]:
 > > Replying to [comment:7 huhabla]:
 > > > Running the script will show that calling functions from a dict is
 50 time faster than using a pipe with a subprocess.
 > >
 > > It seems that this is something we need to take care of. And this is
 something what my factory pattern suggestions is trying to address.
 > >
 > > We would need to create two sets of class with identical interface.
 One using `RPCServer` (safe) the other calling ctypes directly (fast).
 Objects should be created by factory, so that the factory will put the
 `RPCServer` into the objects, so the user does not take care of it. Maybe
 in Python we can go beyond the classic factory pattern and create also the
 `RPCServer`-dependent classes from the classes calling ctypes directly.
 > >
 > > I realize that ''some code'' would be appreciated but I cannot dive
 into this more now.
 >
 > I am not sure if i understand your approach, so code examples would be
 very helpful here. :)

 My original idea does not involved RCP server, it was about ctypes calls
 versus module calls. It would require rewrite the whole pyGRASS using
 modules. Here is sample pseudo code:

 {{{
 #!python
 # in module/package pygrass
 class Point(object):
     def __init__(self, x=0, y=0, z=None, **kargs):
         # ...
         libvect.Vect_append_point(self.c_points, x, y, z)

 # in module/package failsafegrass
 class Point(object):
     def __init__(self, x=0, y=0, z=None)
         data = "P 1 1\n{x} {y}\n1 1".format(x=x, y=y)
         # ... (fill file /tmp/ef5s with data)
         run_command('v.edit' -n tool='add' map=vectmap input="/tmp/ef5s")

 # in some other modules/packages
 class FailSafeFactory(object):
     def create_Point(self, args, kwargs):
         return failsafegrass.Point(*args, **kwargs)

 class FastFactory(object):
     def create_Point(self, args, kwargs):
         return pygrass.Point(*args, **kwargs)

 # in the user code (probably GUI)

 # at the beginning
 if be_safe:
     factory = FailSafeFactory()
 else:
     factory = FastFactory()

 # usage in code
 point1 = factory.create_Point(x=500, y=600)

 # now I don't know which point it is but the interface is the same
 }}}

 I'm not sure if factory pattern is the right thing to use with RCP server
 (to hide it). But I think that it is the option which should be
 considered. There are two things I don't understand yet. First, how to
 work objects. I can pass them but how I call the methods and access
 attributes in general?

 {{{
 #!python
 class Point:
     def get_x(self):
        return rcpserver.call(self._unsafe_get_x())
 }}}

 But this cannot work for object containing pointers, so there actually
 cannot be any `_unsafe_get_x` method. So, the second thing is that I
 probably need some `ProxyPoint` which can be passed between processes. And
 using some identifier it would be associated with the object on the other
 site.

 {{{
 #!python
 # in the GUI process
 class ProxyPoint:
     def get_x(self):
        return rcpserver.method_call(self, 'get_x')

 # somewhere in the other unsafe process
 # proxy_object == self from above
 # method == 'get_x' from above
 real_object = objects[proxy_object.uid]
 return getattr(real_object, method)()

 # maybe pass only the uid is better idea,
 # since server should not be passed through itself
 }}}

 I don't have more now. It seems to me that this might be possible. But my
 understanding of problem is not complete and even now I see some problems
 such as function/method parameters which are proxy objects.

-- 
Ticket URL: <http://trac.osgeo.org/grass/ticket/2134#comment:12>
GRASS GIS <http://grass.osgeo.org>



More information about the grass-dev mailing list