问题
I found this example of C++ Python binding: Calling C/C++ from python? According to the answer there, I created some testfiles:
foo.cpp:
#include <iostream>
#include <utility>
int bar_2(int a, int b){
return a*b;
}
std::pair<int, int> divide(int dividend, int divisor)
{
return std::make_pair(dividend / divisor, dividend % divisor);
}
extern "C" {
int bar_2_py(int a, int b){ return bar_2(a,b); }
std::pair<int, int> divide_py(int d, int div){return divide(d,div);}
}
fooWrapper.py:
#!/usr/bin/env python
from ctypes import cdll
lib = cdll.LoadLibrary('./libfoo.so')
def bar_2(a, b):
res = lib.bar_2_py( a,b )
return res
def divide(d,div):
res = lib.divide_py(d,div)
return res
Then
g++ -c -fPIC foo.cpp -o foo.o
g++ -shared -Wl,-soname,libfoo.so -o libfoo.so foo.o
creates libfoo.so
If I import it and run the functions in iPython I get the right value for function "bar_2" but a (partly) wrong answer for "divide":
from fooWrapper import bar_2, divide
bar_2(10,2) # returns 20, which is right
divide(10,3) # returns 3
Obviously, the return-value is right for the first value of the pair (as 10/3 int division is 3). But the second value was getting lost.
So, what would be best practice to obtain multiple values (in this case 2 integer values)?
Thank you!
回答1:
I don't think ctypes
allows one to translate std::pair
to a python tuple without much boilerplate code. Especially since std::pair
is a feature of the c++11
standard, and ctypes
only works with c
-style functions [citation / verification needed].
I suggest would using output parameters, the c
way to return multiple values. The idea is simple, the c
-function returns it's values by pointer, example.c
:
void divide_modulo(int a, int b, int *div, int *rest)
{
*div = a / b;
*rest = a % b;
}
Then compile it to a shared library:
gcc -o libexample.so -shared example.c
The libexample.so
now allows you to write to python integers via a pointer in c
which are passes as parameters like this:
import ctypes
lib = ctypes.cdll.LoadLibrary('./libexample.so')
def divide_modulo(a, b):
div = ctypes.c_int(0)
rest = ctypes.c_int(0)
lib.divide_modulo(a, b, ctypes.byref(div), ctypes.byref(rest))
return (div.value, rest.value)
print(divide_modulo(11, 4))
The ctypes.byref
wrapper when calling lib.divide_modulo
with div
and rest
converts an int
to a pointer to an int
.
来源:https://stackoverflow.com/questions/31835398/c-python-binding-with-ctypes-return-multiple-values-in-function