【问题标题】:boost::python: howto call a function that expects a pointer?boost::python: 如何调用需要指针的函数?
【发布时间】:2010-10-07 12:09:53
【问题描述】:

我有一个函数,它接受一个 int 指针并通过 boost::python 公开它。如何从 python 调用这个函数?

在 C++ 中使用 boost::python:

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

在python中:

import foo_ext
i = 12
foo_ext.foo(i)

结果

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)

那么如何传递指针呢?

【问题讨论】:

    标签: python pointers boost-python


    【解决方案1】:

    在大多数情况下,您可以避免将原始指针传递给函数,但是当确实需要时,您可以使用适配器为指向原始对象的 C++ 指针创建 Python 对象:

    template<typename PtrT>
    struct PtrAdapter {
        auto& get(PtrT ptr)  { return *ptr; }
    };
    

    然后定义指针类型到 Python 对象的映射并允许隐式转换:

    class_<Cluster<LinksT>*, noncopyable>(typpedName<LinksT>("ClusterPtr", true, true)
    , "Raw hierarchy cluster pointer\n")
        .def("__call__", &PtrAdapter<Cluster<LinksT>*>::get,
            return_internal_reference<>(),
            "referenced cluster")
        ;
    register_ptr_to_python<Cluster<LinksT>*>();
    

    请注意,原始对象类型也应该映射到 Python 对象(在本例中为 Cluster&lt;LinksT&gt;)。

    那么对于这样的 C++ 代码:

    Cluster<LinksT>* cl = clusters.head();
    process(cl);
    Id cid = cl->id();
    

    你可以使用类似的 Python 代码:

    cl = clusters.head()
    process(cl)
    cid = cl.id()
    

    【讨论】:

      【解决方案2】:

      简短的回答是:你不能。 Python没有指针

      长答案是:根据用例有各种解决方法。

      我注意到您在示例中使用了 int 和 int*。 Int(连同 float、str 和 bool)是一种特殊情况,因为它在 python 中是不可变的。

      假设您传入的对象并不是真正的 int。

      有一个包装函数,它将参数作为引用,获取地址并将其传递给实际函数。这将在 python 中无缝运行。


      好的,所以说它确实是一个 int。现在你有问题了。您无法更改传入的 int。如果您尝试相同的解决方案,boost::python 将在运行时抱怨 l-values。还有几个选择。

      假设您不需要在函数退出后查看 int 的样子,并且您知道函数不会在函数返回后将指向解引用的指针隐藏起来:

      您的包装器现在应该通过值或 const 引用来获取 int。其他一切都一样。


      也许你只需要看到 after 状态(int 是一个 OUT 边界):

      您的包装函数现在将不接受任何参数,并将本地 int 的地址传递给实际函数。它将返回该值。如果你的函数已经有一个返回值,它现在应该返回一个元组。


      输入和输出都很重要,你知道函数不会在函数返回后将指向解引用的指针隐藏起来:

      结合以上两者。包装器按值获取一个 int 并返回一个不同的 int。


      该函数期望在函数返回后将指向解引用的指针隐藏起来:

      没有真正好的解决方案。您可以在 c++ 中创建和公开一个包含 c++ int 的对象。包装器将通过引用获取该对象,提取包含的 int 的地址并将其传递给实际函数。保持对象在 python 中的活动(并且不受垃圾收集器的影响)直到库完成它现在是 python 编写器的问题,如果他搞砸了数据损坏或解释器崩溃。

      【讨论】:

      • [quote]也许你只需要看到 after 状态(int 是一个 OUT 边界):你的包装函数现在将不接受任何参数,并将本地 int 的地址传递给实际功能。它将返回该值。如果你的函数已经有一个返回值,它现在应该返回一个元组。 [/quote] 这正是我想要实现的。你如何在代码中做到这一点?
      • int foo_w() {int i;富(&i);返回我; }
      【解决方案3】:

      来自python.org's boost.python HowTo

      也许你想要结果 包含原始指针的 Python 对象 争论?在这种情况下, 需要注意的是,如果 C++ 对象在对象之前结束 Python 对象,该指针将 悬挂和使用 Python 对象可能 导致崩溃。

      以下是公开可变 C++ 的方法 模块初始化期间的对象:

      scope().attr("a") = object(ptr(&class_instance));
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多