> On 04/10/2012 02:11 AM, Travis Oliphant wrote:
>> Hi all,
>> 
>> Some of you are aware of Numba.   Numba allows you to create the equivalent 
>> of C-function's dynamically from Python.   One purpose of this system is to 
>> allow NumPy to take these functions and use them in operations like ufuncs, 
>> generalized ufuncs, file-reading, fancy-indexing, and so forth.  There are 
>> actually many use-cases that one can imagine for such things.
>> 
>> One question is how do you pass this function pointer to the C-side.    On 
>> the Python side, Numba allows you to get the raw integer address of the 
>> equivalent C-function pointer that it just created out of the Python code.   
>>  One can think of this as a 32- or 64-bit integer that you can cast to a 
>> C-function pointer.
>> 
>> Now, how should this C-function pointer be passed from Python to NumPy?   
>> One approach is just to pass it as an integer --- in other words have an API 
>> in C that accepts an integer as the first argument that the internal 
>> function interprets as a C-function pointer.
>> 
>> This is essentially what ctypes does when creating a ctypes function pointer 
>> out of:
>> 
>>   func = ctypes.CFUNCTYPE(restype, *argtypes)(integer)
>> 
>> Of course the problem with this is that you can easily hand it integers 
>> which don't make sense and which will cause a segfault when control is 
>> passed to this "function"
>> 
>> We could also piggy-back on-top of Ctypes and assume that a ctypes 
>> function-pointer object is passed in.   This allows some error-checking at 
>> least and also has the benefit that one could use ctypes to access a 
>> c-function library where these functions were defined. I'm leaning towards 
>> this approach.
>> 
>> Now, the issue is how to get the C-function pointer (that npy_intp integer) 
>> back and hand it off internally.   Unfortunately, ctypes does not make it 
>> very easy to get this address (that I can see).    There is no ctypes C-API, 
>> for example.    There are two potential options:
>> 
>>      1) Create an API for such Ctypes function pointers in NumPy and use the 
>> ctypes object structure.  If ctypes were to ever change it's object 
>> structure we would have to adapt this API.
>> 
>>      Something like this is what is envisioned here:
>> 
>>           typedef struct {
>>                              PyObject_HEAD
>>                              char *b_ptr;
>>                   } _cfuncptr_object;
>> 
>>      then the function pointer is:
>>      
>>          (*((void **)(((_sp_cfuncptr_object *)(obj))->b_ptr)))
>> 
>>      which could be wrapped-up into a nice little NumPy C-API call like
>> 
>>      void * Npy_ctypes_funcptr(obj)
>> 
>> 
>>      2) Use the Python API of ctypes to do the same thing.   This has the 
>> advantage of not needing to mirror the simple _cfuncptr_object structure in 
>> NumPy but it is *much* slower to get the address.   It basically does the 
>> equivalent of
>> 
>>      ctypes.cast(obj, ctypes.c_void_p).value
>> 
>> 
>>      There is working code for this in the ctypes_callback branch of my 
>> scipy fork on github.
>> 
>> 
>> I would like to propose two things:
>> 
>>      * creating a Npy_ctypes_funcptr(obj) function in the C-API of NumPy and
>>      * implement it with the simple pointer dereference above (option #1)
>> 
>> 
>> Thoughts?
> 
> I really hope we can find some project-neutral common ground, so that lots of 
> tools (Cython, f2py, numba, C extensions in NumPy and SciPy) can agree on how 
> to "unbox callables".
> 
> A new extension type in NumPy would not fit this bill I feel. I've created a 
> specification for this; if a number of projects (the ones mentioned above) 
> agree on this or something similar and implement support, we could propose a 
> PEP and do it properly once it has proven itself.
> 
> http://wiki.cython.org/enhancements/cep1000
> 
> In Cython, this may take the form
> 
> def call_callback(object func):
>    cdef double (*typed_func)(int)
>    typed_func = func
>    return typed_func(4)
> 
> ...it would be awesome if passing a Numba-compiled function just worked in 
> this example.

Yes, I think we should go the Python PEP route.   However, it will take some 
time to see that to completion (especially with ctypes already in existence).   
Dag, this would be a very good thing for you to champion however ;-)  

In the mean-time, I think we could do as Robert essentially suggested and just 
use Capsule Objects around an agreed-upon simple C-structure:

        int   id   /* Some number that can be used as a "type-check" */
        void *func; 
        char *string; 

We can then just create some nice functions to go to and from this form in 
NumPy ctypeslib and then use this while the Python PEP gets written and adopted.

-Travis





> 
> Dag

_______________________________________________
NumPy-Discussion mailing list
[email protected]
http://mail.scipy.org/mailman/listinfo/numpy-discussion

Reply via email to