Python与ctypes绑定-在函数中返回多个值

C++ - Python Binding with ctypes - Return multiple values in function

本文关键字:返回 函数 ctypes 绑定 Python      更新时间:2023-10-16

我找到了这个c++ Python绑定的例子:从python调用C/c++ ?根据答案,我创建了一些测试文件:

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
然后

g++ -c -fPIC foo.cpp -o foo.o
g++ -shared -Wl,-soname,libfoo.so -o libfoo.so  foo.o

创建libfoo.so

如果我导入它并在iPython中运行函数,我会得到函数"bar_2"的正确值,但"divide"的(部分)错误答案:

from fooWrapper import bar_2, divide
bar_2(10,2) # returns 20, which is right
divide(10,3) # returns 3

显然,返回值对第一个值是正确的(因为10/3 int除法是3)。但是第二个值丢失了。

那么,获得多个值(在本例中为2个整数值)的最佳实践是什么?

谢谢!

我不认为ctypes允许在没有太多样板代码的情况下将std::pair转换为python元组。特别是因为std::pairc++11标准的一个特性,而ctypes只适用于c风格的函数[需要引用/验证]。

我建议使用输出参数c方式返回多个值。这个想法很简单,c -函数通过指针返回它的值,example.c:

void divide_modulo(int a, int b, int *div, int *rest)
{
    *div  = a / b;
    *rest = a % b;
}

然后编译成一个共享库:

gcc -o libexample.so -shared example.c

libexample.so现在允许您通过c中的指针写入python整数,该指针作为参数传递,如下所示:

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))

divrest调用lib.divide_modulo时,ctypes.byref包装器将int转换为指向int的指针。