2011-12-29 10 views

risposta

6

L'interfaccia _PyGObject_API è stata modificata a un certo punto. Avevo bisogno di abbandonare la funzione register_sinkfunc. Le seguenti opere:

from gi.repository import Gio, GLib 
import gi 
import ctypes 

class _PyGObject_Functions(ctypes.Structure): 
    _fields_ = [ 
     ('register_class', 
     ctypes.PYFUNCTYPE(ctypes.c_void_p, ctypes.c_char_p, 
          ctypes.c_int, ctypes.py_object, 
          ctypes.py_object)), 
     ('register_wrapper', 
     ctypes.PYFUNCTYPE(ctypes.c_void_p, ctypes.py_object)), 
     ('lookup_class', 
     ctypes.PYFUNCTYPE(ctypes.py_object, ctypes.c_int)), 
     ('newgobj', 
     ctypes.PYFUNCTYPE(ctypes.py_object, ctypes.c_void_p)), 
     ] 

class PyGObjectCPAI(object): 
    def __init__(self): 
     PyCObject_AsVoidPtr = ctypes.pythonapi.PyCObject_AsVoidPtr 
     PyCObject_AsVoidPtr.restype = ctypes.c_void_p 
     PyCObject_AsVoidPtr.argtypes = [ctypes.py_object] 
     addr = PyCObject_AsVoidPtr(ctypes.py_object(
      gi._gobject._PyGObject_API)) 
     self._api = _PyGObject_Functions.from_address(addr) 

    def pygobject_new(self, addr): 
     return self._api.newgobj(addr) 

capi = PyGObjectCPAI() 

per ottenere un oggetto da un puntatore:

obj = capi.pygobject_new(pointer) 

per ottenere un puntatore da un (g) oggetto:

pointer = hash(obj) 

devo aggiungere, in Nel mio caso questo non mi ha aiutato a risolvere il mio problema reale. Stavo cercando di interfacciare con dconf, ma dconf restituisce i valori di tipo GVariant, che non eredita da GObject. Sembra che PyGI/GObject sfortunatamente non esponga le funzioni necessarie per trasformare un C (* GVariant) in un Python GLib.Variant. Immagino sia di quelle volte in cui devi buttare via il tuo approccio iniziale e provare qualcosa di diverso.

0

Con l'avvento dei file di instrospection (.typelib, .gir), la stessa API deve essere disponibile indipendentemente dalla lingua utilizzata, ovvero se si sta utilizzando una funzione C non nell'API, probabilmente si sta utilizzando una funzione destinata ad essere utilizzata solo internamente.

+2

In teoria è vero. Tuttavia volevo usare una funzione da libdconf, e al momento non esiste alcun collegamento per questo sul mio sistema operativo (Ubuntu Oneric). Inoltre, è pensabile che si debba gestire una libreria personalizzata (non parte di Gtk & co.) Che restituisca un puntatore a un oggetto GObject, quindi in casi di nicchia potrebbe comunque essere utile. – jdm

+0

@jdm Vedo, grazie per il vostro feedback. – jcollado

2

Il codice jdm's answer non è compatibile con Python 3. Poiché CObject è deprecated in Python 2.7 e 3.1, e rimosso iniziando con 3.2, ho modificato il codice per utilizzare Capsule (available in 2.7 e dal 3.1):

import ctypes, gi 

class _PyGObject_Functions(ctypes.Structure): 
    _fields_ = [ 
     ('register_class', 
      ctypes.PYFUNCTYPE(ctypes.c_void_p, ctypes.c_char_p, 
       ctypes.c_int, ctypes.py_object, ctypes.py_object)), 
     ('register_wrapper', 
      ctypes.PYFUNCTYPE(ctypes.c_void_p, ctypes.py_object)), 
     ('lookup_class', 
      ctypes.PYFUNCTYPE(ctypes.py_object, ctypes.c_int)), 
     ('newgobj', 
      ctypes.PYFUNCTYPE(ctypes.py_object, ctypes.c_void_p)), 
     ] 

class PyGObjectCAPI(object): 
    def __init__(self): 
     self._as_void_ptr.restype = ctypes.c_void_p 
     self._as_void_ptr.argtypes = [ctypes.py_object] 
     addr = self._as_void_ptr(ctypes.py_object(
      gi._gobject._PyGObject_API)) 
     self._api = _PyGObject_Functions.from_address(addr) 

    @staticmethod 
    def _as_void_ptr(obj): 
     name = ctypes.pythonapi.PyCapsule_GetName(obj) 
     return ctypes.pythonapi.PyCapsule_GetPointer(obj, name) 

    def pygobject_new(self, addr): 
     return self._api.newgobj(addr) 

capi = PyGObjectCAPI() 

(ho anche rinominato a PyGobjectC API -. non sono sicuro se CPAI stava per qualcosa, ma ha fatto più senso per me in questo modo)

1

PyGOject api cambiato da AlliedEnvy update

import gi 
import ctypes 
from ctypes import pythonapi 

class _PyGObject_Functions(ctypes.Structure): 
    _fields_ = [ 
     ('pygobject_register_class', 
      ctypes.PYFUNCTYPE(ctypes.c_void_p)), 
     ('pygobject_register_wrapper', 
      ctypes.PYFUNCTYPE(ctypes.c_void_p)), 
     ('pygobject_lookup_class', 
      ctypes.PYFUNCTYPE(ctypes.c_void_p)), 
     ('pygobject_new', 
      ctypes.PYFUNCTYPE(ctypes.py_object, ctypes.c_void_p)), 
     ] 

    class PyGObjectCAPI(object): 
    def __init__(self): 
     addr = self._as_void_ptr(gi._gobject._PyGObject_API) 
     self._api = _PyGObject_Functions.from_address(addr) 

    @classmethod 
    def _capsule_name(cls, capsule): 
     pythonapi.PyCapsule_GetName.restype = ctypes.c_char_p 
     pythonapi.PyCapsule_GetName.argtypes = [ctypes.py_object] 
     return pythonapi.PyCapsule_GetName(capsule) 

    @classmethod 
    def _as_void_ptr(cls, capsule): 
     name = cls._capsule_name(capsule) 
     pythonapi.PyCapsule_GetPointer.restype = ctypes.c_void_p 
     pythonapi.PyCapsule_GetPointer.argtypes = [ 
      ctypes.py_object, ctypes.c_char_p] 
     return pythonapi.PyCapsule_GetPointer(capsule, name) 

    def to_object(self, addr): 
     return self._api.pygobject_new(addr) 

capi = PyGObjectCAPI()