2011-01-17 2 views
1

Ich habe einige Code, der eine C-Funktion kompiliert, um eine numpy generische Funktion mit Hilfe von PyUFunc_FromFuncAndData zu erstellen. Ich habe etwas Cython geschrieben, um die Ufunc zu erstellen, aber ich würde es gerne mit Ctypes machen, wenn es möglich ist, da ich es verteilen möchte, und ich möchte Benutzern den Kompilierungsschritt ersparen.Wrapping eine Funktion, die einen Zeiger auf ein Python-Objekt mit Ctypes

Das Problem ist, dass PyUFunc_FromFuncAndData einen Zeiger auf ein PyObject zurückgibt. Ist es möglich, es als Objekt aus Python-Code zu verwenden?

Grundsätzlich würde ich in der Lage sein wie der folgenden cython Code zu Python/ctypes zu übersetzen:

restype dieser Funktion
from numpy cimport NPY_DOUBLE 
from libc.stdlib cimport malloc, free 

cdef extern from "numpy/ufuncobject.h": 
    ctypedef void (*PyUFuncGenericFunction) (char **, Py_ssize_t *, Py_ssize_t *, void *) 
    object PyUFunc_FromFuncAndData (PyUFuncGenericFunction *, void **, char *, int, int, int, int, char *, char *, int) 
    void import_ufunc() 

import_ufunc() 


cdef class UFuncWrapper: 

    cdef readonly object func 
    cdef object _llvm_func 
    cdef PyUFuncGenericFunction function 
    cdef char *types 
    cdef bytes name 

    def __init__(self, func, ufunc, long long ptr): 
     self._llvm_func = ufunC# keep a ref to prevent it from being gced 
     cdef int num_args = len(func.args) 
     self.types = <char*>malloc(sizeof(char)*(num_args+1)) 
     self.name = func.name 
     cdef int i 
     for i in range(num_args+1): 
      self.types[i] = NPY_DOUBLE 
     self.function = <PyUFuncGenericFunction>ptr 
     self.func = PyUFunc_FromFuncAndData(
      &self.function, 
      NULL, 
      self.types, 
      1, #ntypes 
      num_args, 
      1, 
      -1, # PyUFunc_None, 
      self.name, 
      self.name, #FIXME: __doc__ 
      0) 

    def __dealloc__(self): 
     free(self.types) 

    def __call__(self, *args): 
     return self.func(*args) 
+0

Ich denke, man bereits die obvoius versucht - das '.restype' Attribut der Funktion' ctypes.POINTER (ctypes.py_object) Einstellung 'und dereferenzieren mit' returned_pointer [0] '? –

Antwort

3

Set ctypes.py_object. Das folgende Beispiel verwendet einen Aufruf von Python C-API, aber es funktioniert das gleiche für alles andere.

import ctypes 
class Foo(object): 
    bar='baz' 

foo=ctypes.py_object(Foo) 
print 'Memory adress of Foo.bar object:', 
print ctypes.pythonapi.PyObject_GetAttrString(foo,'bar') # prints the pointer 

ctypes.pythonapi.PyObject_GetAttrString.restype = ctypes.py_object 

print 'Actual Foo.bar after we set restype correctly:', 
print ctypes.pythonapi.PyObject_GetAttrString(foo,'bar') # prints "baz" 
Verwandte Themen