Passing a numpy function in python to C++ using SWIG directors
Question: My code is mainly in C++, but I want to use the SWIG director option to
redefine a C++ virtual function in python, and then pass that function back to
C++. The following is a simplified example.

Here is my base class in C++ with a virtual function `fun`. `fun` takes in
`(double* x, int n)` which allows me to pass a numpy array into it.

    
    
    class base{
    public:
        virtual double fun(double* x, int n){return 0.0;}
    };
    

I have another class which takes in this base class:

    
    
    class main{
    public:
        base* b_;
    
        main(base& b){
            b_ = &b; 
        }
    };
    

This class has a constructor which takes in a base class and stores a pointer
to it (`b_`).

I can successfully compile the swig interface into a module named `mymodule`
making sure to enable directors (see SWIG interface file below), and, as per
the SWIG director documentation, I inherit the base class and redefine the
virtual function `fun` as follows:

    
    
    import mymodule
    class base(mymodule.base):
        def __init__(self):
            super(base,self).__init__()
        def fun(self,x):
            return x[0]
    

Then I pass it into the `main` class:

    
    
    b = base()
    m = mymodule.main(b)
    

However, when I try `m.b_.fun(array([1.,2.]))` I get a `TypeError`:

    
    
    TypeError: 'SwigPyObject' object has no attribute '__getitem__'
    

Any ideas on how to get this to work? I think when I pass `b` into
mymodule.main, C++ is seeing `x` as a double * pointer and doesn't know what
to do with it.

By the way, here is my swig interface file:

    
    
    %module(directors="1") mymodule
    
    %{
    #define SWIG_FILE_WITH_INIT
    /* Includes the header in the wrapper code */
    #include "myclasses.h"
    %}
    
    %feature("director") base;
    
    %init %{
    import_array();
    %}
    
    %apply (double* IN_ARRAY1, int DIM1) {(double* x, int n)};
    
    /* Parse the header file to generate wrappers */
    %include "myclasses.h"
    


Answer: It looks like an ownership issue from Python.

Provide a hint to SWIG:

    
    
    %new double *fun(double* IN_ARRAY1, int DIM1) {(double* x, int n)};
    

Notice the pointer to the function itself as well. The Python module will
assign proper ownership of the object(s) when %new is used. That's why you can
use values but not variables in the call.

