Get address of a (CFUNCTYPE) def function from a cdef function in a pyx file

Viewed 187

I'm using ctypesgen and ctypesgen_to_pxd to generate both a ctypes wrapper for a given native library as well as a pxd containing those types.

I'm able to use the generated ctypes wrapper to call into native code from Python very easily. What I can't figure out how to do is to return a function pointer of a Python callback back via a hand-written pyx (see below) to my native library, which can then call that function pointer to execute some Python code.

Here is a complete and runnable sample on Github that shows my problem. You can build it using the provided build-and-run.sh or use VS Code remote containers to open the workspace. This latter method also allows you to debug and recompile as opposed to using the shell script = docker build + run.

The contents of cythoncallbacks.pyx.in is below for quick reference

# cython: language_level=3

import sys
sys.path.insert(0, '')

from ctypes import *
from nativelib cimport *
import nativelib as n


@CFUNCTYPE(UNCHECKED(n.NativeResult), n.NativeLibHdl)
def python_cfunctype_callback(libHdl) -> n.NativeResult:
    print("Do stuff in a CFUNCTYPE Python function here...")
    return n.NativeResult(n.RESULT_OK)

def python_regular_callback(libHdl: n.NativeLibHdl) -> n.NativeResult:
    print("Do stuff in a regular Python callback here...")
    return n.NativeResult(n.RESULT_OK)

cdef public NativeResult cythoncallbacks_getcallbacks(NativeLibHdl libHdl, CallbackParams params, NativeCallbacksHdl callbacksHdl):
    # How do I call python_cfunctype_callback or python_regular_callback from here?
    # Both ways below won't compile

    ###################################################
    
    # Errors out with
    # Cannot convert Python object to CallbackFunc* or
    # From https://stackoverflow.com/a/33485103/802203
    
    # callbacksHdl.callback = python_cfunctype_callback

    ###################################################
    
    # Errors out with
    # Storing unsafe C derivative of temporary Python reference
    # from https://stackoverflow.com/questions/2038839/python-ctypes-addressof-cfunctype
    
    # callbacktype = CFUNCTYPE(UNCHECKED(n.NativeResult), n.NativeLibHdl)
    # callbacksHdl.callback = callbacktype(python_cfunctype_callback)

    ####################################################################################

    return NativeResult(RESULT_NOT_IMPLEMENTED)

The sections above within the ###################### lines is what I'm trying to figure out. Ideally I'd prefer to use python_regular_callback if possible so I can load the appropriate module methods dynamically like I would with a dlopen and dlsym.

Thanks in advance, always glad to clarify or provide more information.

0 Answers
Related