Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

boost::python: howto call a function that expects a pointer?

I have a function that takes an int-pointer and exposed it via boost::python. How can I call this function from python?

in C++ with boost::python:

void foo(int* i);
...
def("foo", foo);

in python:

import foo_ext
i = 12
foo_ext.foo(i)

results in

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
Boost.Python.ArgumentError: Python argument types in
foo(int)
did not match C++ signature:
foo(int* i)

So how to pass a pointer?

like image 412
Philipp Avatar asked Oct 07 '10 12:10

Philipp


1 Answers

Short answer is: You can't. Python does not have pointers

Long answer is: There are assorted workarounds depending on use-case.

I notice that you are using an int and an int* in your example. Int (along with float, str, and bool) is a special case because it is immutable in python.

Lets say that the object that you are passing in is not really an int.

Have a wrapper function that takes the argument as a reference, takes the address and passes it on to the actual function. This will work seamlessly in python.


Ok, so say it really was an int. Now you have a problem. You can not change the int you passed in. If you try the same solution, boost::python will complain about l-values at runtime. There are still several options.

Let's say that you do not need to see what the int looks like after the function exits and you know that the function will not squirrel away the pointer to dereference after the function returns:

Your wrapper should now take the int by value or by const reference. Everything else is the same.


Maybe you ONLY need to see the after state (the int is an OUT perimeter):

Your wrapper function will now take no arguments, and will pass the address of a local int to the actual function. It will return that value. If you function already has a return value it should now return a tuple.


Both the input and the output are important and you know that the function will not squirrel away the pointer to dereference after the function returns:

Combine the two above. The wrapper takes one int by value and returns a different int.


The function expects to squirrel away the pointer to dereference after the function returns:

There is no real good solution. You can create and expose an object in c++ that contains a c++ int. The wrapper will take that object by reference, extract the address of the contained int and pass it on to the actual function. Keeping the object alive in python (and safe from the garbage collector) until the library is done with it is now the python writer's problem, and if he goofs the data is corrupt or the interpretor crashes.

like image 143
Matthew Scouten Avatar answered Sep 28 '22 01:09

Matthew Scouten