我有一个函数,它接受一个int-pointer并通过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)
那么如何传递指针?
答案 0 :(得分:4)
简短回答:你不能。 Python没有指针
答案很长:根据用例,有各种变通方法。
我注意到你在你的例子中使用了int和int *。 Int(以及float,str和bool)是一种特殊情况,因为它在python中是不可变的。
有一个包装函数,它将参数作为参考,获取地址并将其传递给实际函数。这将在python中无缝地工作。
好的,所以说它真的是一个int。现在你有问题了。你无法改变你传入的int。如果你尝试相同的解决方案,boost :: python会在运行时抱怨l值。还有几种选择。
您的包装器现在应该通过值或const引用获取int。其他一切都是一样的。
您的包装函数现在不带参数,并将本地int的地址传递给实际函数。它将返回该值。如果你的函数已经有一个返回值,它现在应该返回一个元组。
结合上面两个。包装器按值获取一个int并返回不同的int。
没有真正好的解决方案。您可以在包含c ++ int的c ++中创建和公开对象。包装器将通过引用获取该对象,提取包含的int的地址并将其传递给实际的函数。保持对象在python中保持活动(并且安全地从垃圾收集器)直到库完成它现在是python writer的问题,如果他蠢事,数据损坏或解释器崩溃。
答案 1 :(得分:1)
来自python.org's boost.python HowTo
也许你会喜欢结果 Python对象包含原始指针 争论?在那种情况下, 需要注意的是,如果一生的话 C ++对象在之前结束 Python对象,指针将 悬挂和使用Python对象可能 导致崩溃。
以下是如何公开可变C ++ 模块初始化期间的对象:
scope().attr("a") = object(ptr(&class_instance));
答案 2 :(得分: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<LinksT>
)。
然后是这样的C ++代码:
Cluster<LinksT>* cl = clusters.head();
process(cl);
Id cid = cl->id();
您可以使用类似的Python代码:
cl = clusters.head()
process(cl)
cid = cl.id()