Función de llamada SWIG punteros almacenados dentro de la estructura

Tengo una estructura de la siguiente manera:

struct power_model { int64_t (*estimate_energy)(statistics *stats, statistics *scaled_stats, parameters *from, parameters *to, energy_container *energy_container); int64_t (*estimate_performance)(statistics *stats, parameters *params); uint32_t (*freq_to_volt)(uint32_t freq); }; 

Hay varios modelos de poder que contiene mi código. Me gustaría envolver estos modelos con SWIG y exponerlos a Python para que pueda ejecutar mis pruebas de unidad.

Mientras que la documentación de SWIG habla sobre la exposición de punteros de función, no habla de punteros de función contenidos dentro de estructuras. Intenté encapsular las llamadas en mi archivo de interfaz

 %{ #include "models.h" %} %include "models.h" %extend power_model { %pythoncallback; int64_t (*estimate_energy)(statistics *stats, statistics *scaled_stats, parameters *from, parameters *to, energy_container *energy_container); int64_t (*estimate_performance)(statistics *stats, parameters *params); uint32_t (*freq_to_volt)(uint32_t freq); %nopythoncallback; } 

También intenté prefijar los nombres de campo con %constant .

Con estos enfoques, siempre termino con el mismo error:

     In [3]: model.estimate_energy() --------------------------------------------------------------------------- TypeError Traceback (most recent call last)  in () ----> 1 model.estimate_energy() TypeError: 'SwigPyObject' object is not callable 

    ¿Cómo puedo llamar a las funciones subyacentes a las que hacen referencia los punteros de función contenidos en struct power_model ?

    Edición : para ampliar mi configuración, también soy fuente de dos archivos adicionales para explicar mejor la configuración que estoy tratando de lograr con la interfaz power_model .

    nexus5.c

     static int64_t estimate_energy(statistics *stats, statistics *scaled_stats, parameters *from, parameters *to, energy_container *energy) { ... } static int64_t estimate_performance(statistics *stats, parameters *params) { ... } static uint32_t freq_to_volt(uint32_t freq) { ... } struct power_model nexus5_power_model = { .estimate_energy = estimate_energy, .estimate_performance = estimate_performance, .freq_to_volt = freq_to_volt, }; 

    galaxy_s.c

     static int64_t estimate_energy(statistics *stats, statistics *scaled_stats, parameters *from, parameters *to, energy_container *energy) { ... } static int64_t estimate_performance(statistics *stats, parameters *params) { ... } static uint32_t freq_to_volt(uint32_t freq) { ... } struct power_model galaxy_s_power_model = { .estimate_energy = estimate_energy, .estimate_performance = estimate_performance, .freq_to_volt = freq_to_volt, }; 

    Esto funciona para mi La solución 5 es la preferida.

    test.i

     %module test %{ #include "test.h" %} // Solution 5 (right one) %pythoncallback; double f5(double); %nopythoncallback; %ignore f5; %include "test.h" 

    prueba.h

     typedef double (*fptr_t)(double); // Solution 5 double f5(double x) { return x*x; } typedef struct bla { fptr_t f; } bla; 

    Desde dentro de Python

     import test s = test.bla # Assign function pointer sf = test.f5 # Execute sf(2) 

    f es una función que toma un puntero a función como argumento