如何在Python中传递数组指针给封装的C++函数

4 投票
1 回答
5998 浏览
提问于 2025-04-15 11:59

我刚开始接触C++和Python混合编程,对Python/C API还不太了解。最近我开始使用Boost.Python来把一个C++库封装成Python可以用的。现在我遇到问题了,想要封装一个函数,这个函数的参数是一个指向数组的指针。下面是这个函数在C++中的原型。

class AAF{
  AAF(AAF_TYPE t);
  AAF(double v0, const double * t1, const unsigned * t2, unsigned T);
  ~AAF();
}

我这样用boost::python封装对吗?

class_<AAF>("AAF", init<AAF_TYPE>())
  .def(init<double, const double*, const unsigned*, unsigned>());

注意,我的代码编译和链接都成功了,但我不知道怎么在Python中调用它。我尝试的一些简单方法都失败了。

>>> z = AAF(10, [4, 5.5, 10], [1, 1, 2], 3);

Traceback (most recent call last):
  File "./test_interval.py", line 40, in <module>
    z = AAF(10, [4, 5.5, 10], [1, 1, 2], 3);
Boost.Python.ArgumentError: Python argument types in
    AAF.__init__(AAF, int, list, list, int)
did not match C++ signature:
    __init__(_object*, AAF_TYPE)
    __init__(_object*, double, double const*, unsigned int const*, unsigned int)

>>> t1 = array.array('d', [4, 5.5, 10])
>>> t2 = array.array('I', [1, 1, 2])
>>> z = AAF(10, t1, t2, 3);

Traceback (most recent call last):
  File "./test_interval.py", line 40, in <module>
    z = AAF(10, t1, t2, 3);
Boost.Python.ArgumentError: Python argument types in
    AAF.__init__(AAF, int, array.array, array.array, int)
did not match C++ signature:
    __init__(_object*, AAF_TYPE)
    __init__(_object*, double, double const*, unsigned int const*, unsigned int)

我还有第二个问题,我需要封装析构函数吗?请告诉我在某些情况下这是否必要,但并不是总需要。

1 个回答

4

包裹的方式是对的(原则上),但是在

AAF(10, [4, 5.5, 10], [1, 1, 2], 3);

(正如解释器所指出的),你传递给函数的是Python的列表对象,而不是指针。

简单来说,如果你的函数只需要处理Python的列表,你需要修改代码,使用Python的列表接口(而不是指针)。如果你需要保持原来的接口,你就得写一个包装函数,这个函数接收Python的列表,进行适当的转换,然后调用你原来的C++函数。对于numpy数组也是一样的。

请注意,boost::python提供了一些内置机制,可以将Python的容器转换为与STL兼容的容器。

针对你的情况,一个示例包装代码可以是

void f(list o) {
    std::size_t n = len(o);
    double* tmp = new double[n];
    for (int i = 0; i < n; i++) {
        tmp[i] = extract<double>(o[i]);
    }
    std::cout << std::endl;
    // use tmp
    delete tmp;
}

请查看boost.python的教程,网址是 http://www.boost.org/doc/libs/1_39_0/libs/python/doc/tutorial/doc/html/index.html

撰写回答