3

Ive been working with Python and C++ together for some time, but never tried to implement what follows:

Id like the python user to be able to write something like:

def foo(a,b):
    return a+b

myclass.myfunc(foo)

where myclass is a c++ class exposed to python with Boost.Python, with one of its methods (myfunc) that takes a function with:

int func(int,int)

signature, and only that.

Is this possible?

Im thinking about declaring:

myclass::myfunc(boost::python::object)

and extracting the typedef'ed function signature, but im just guessing..

maybe there's a better/feasible way to do this, maybe with some 'function' object?

2
  • maybe a better title would have been 'python function as parameter to boost::python c++ exposed class' Commented Nov 20, 2011 at 8:46
  • 1
    This is an interesting question and I'm curious to see the answer. Commented Nov 20, 2011 at 9:19

1 Answer 1

3

You pretty much guessed the answer. Python functions are indeed just boost::python::object instances. You can then just have a boost::function<int (int, int)> and put the Python object inside that.

I just installed my OS and I don't have Boost yet, so I can't test it, but I think it will work if you just do this (without any wrapper functions):

void function(boost::function<int (int, int)> func) {
    // ...
}

// And then you expose the function as you normally would

I expect the above to work; if it doesn't this surely will:

void function_wrap(boost::python::object func)
{
    auto lambda = [func](int a, int b) -> int {
        return boost::python::extract<int>(func(a, b));
    };
    function(boost::function<int (int, int)>(lambda));
}

// And then you expose the wrapper, not the original function
Sign up to request clarification or add additional context in comments.

11 Comments

that is what i was after.. ill test it asap and post results, thank you
Interesting. What does ::boost::python do if func is not a callable? I presume ::boost::python::object has a templated version of operator () to make this work.
@Omnifarious Yes, there's a templated operator(). In case the object is not callable there's an exception thrown (I can't remember what it was called) — pretty much the same thing that happens when you try to call an uncallable object in Python.
Ok.. so: the first one doesnt work, it (predictably) complains about not having a converter to get a boost::function from a boost::python::object, then I upgraded to g++ 4.5 (in order o use lambdas) and works great. Now, can you tell me exactly how can it be? please forgive my ignorance.. but even if I know about lambdas I cant figure it out WHY it does work.. and whats that function() at the last line? Thanx in advance
@user815129 function is your original function; function_wrap is a helper function that makes your C++ code compatible with Python. Your original function expects to receive a function object, so you can't pass it an int; instead you pass it a lambda that will call the python::object and convert its return type to int.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.