请问这样的 C++函数如何用 pybind11 绑定?

2019-07-15 10:12:46 +08:00
 Huelse

我想将以下类中的方法通过 pybind11 绑定到 python 中使用,但无奈看了好一会儿官方文档没有找到合适的例子(可能我眼瞎),所以来 V2 请求各位支招

class SEALContext
{
	...
    static auto Create(const EncryptionParameters &parms,
        bool expand_mod_chain = true,
        sec_level_type sec_level = sec_level_type::tc128)
	{
     	return std::shared_ptr<SEALContext>(
		new SEALContext(
			parms,
			expand_mod_chain,
			sec_level,
			MemoryManager::GetPool())
		);
	}
    ...
}

绑定 wrapper.cpp 中我是这么写的能编译通过:

PYBIND11_MODULE(seal, m) {
	py::class_<SEALContext>(m, "SEALContext")
		.def("Create", &SEALContext::Create)
}

我想在 Python 中 SEALContext.Create(parms)这样调用,经测试,Python 总是提示我需要传入三个参数,但我只想传入 parms 这一个,如果我在 wrapper.cpp 中限定,就编译不通过,然后不知道该怎么做了。。。 感谢各位了!

3587 次点击
所在节点    C++
18 条回复
wutiantong
2019-07-15 10:20:23 +08:00
直接用 lambda 定义好了。
wutiantong
2019-07-15 10:22:04 +08:00
.def("Create", [] (const EncryptionParameters &parms) { return SEALContext::Create(parms); } )

就像这个样子。
Huelse
2019-07-15 11:22:31 +08:00
@wutiantong #2 哇,我还在想这个咋用,感谢!~
Huelse
2019-07-15 20:16:43 +08:00
@wutiantong 呃,遇到了个新问题,请问你知道
```
double free or corruption (out)
Aborted (core dumped)
```
错误怎么处理吗?
https://github.com/pybind/pybind11/issues/1839
我按照这个,弄不好呀
wutiantong
2019-07-16 00:20:17 +08:00
@Huelse double free 广泛存在于 C++程序中,本质上就是对动态申请的内存两次执行 free(),这类问题在很多场景下都可能出现,所以在不清楚你的代码的情况下我是帮不到你的。
wutiantong
2019-07-16 00:21:18 +08:00
至少你需要定位到程序挂掉的那个位置。
Huelse
2019-07-16 08:23:37 +08:00
@wutiantong #5 好的,这个是微软 SEAL 库的源码,我首先想的是我 pybind11 里写的有问题
wutiantong
2019-07-16 09:38:18 +08:00
@Huelse 我看到那个 issue 原来就是你提的,看到了代码后我发现问题应该是在于:
key_context_data() 这个方法的返回值类型是 std::shared_ptr<ContextData>,然而你的 binding 并没有做任何 wrapping 处理,并且在 test.py 里直接把它当作 ContextData 来调用了( context.key_context_data().parms() 这行 )
Huelse
2019-07-16 10:46:44 +08:00
@wutiantong #8 是的,原谅我第一次接触,我还在想怎么弄😂
Huelse
2019-07-16 15:41:00 +08:00
@wutiantong #8
pybind11 文档给我的方案有两个,但都好像是要改 c++代码的,我不希望这样。
https://pybind11.readthedocs.io/en/master/advanced/smart_ptrs.html#std-shared-ptr

```
inline auto key_context_data() const
{
auto data = context_data_map_.find(key_parms_id_);
return (data != context_data_map_.end()) ?
data->second : std::shared_ptr<ContextData>{ nullptr };
}
```
我想问题应该是这里的,请问我该怎么做?
wutiantong
2019-07-16 15:52:18 +08:00
@Huelse

看起来只需要把
// SEALContext::ContextData
py::class_<SEALContext::ContextData>(m, "SEALContext::ContextData")

改成
py::class_<SEALContext::ContextData, std::shared_ptr<SEALContext::ContextData>>(m, "SEALContext::ContextData")

就行了。
Huelse
2019-07-16 16:38:31 +08:00
@wutiantong #11 我透,还真是这样!我该怎么感谢你
wutiantong
2019-07-16 17:11:47 +08:00
@Huelse 不用谢~
Huelse
2019-07-17 22:38:09 +08:00
@wutiantong #13
尴尬。。这次遇到了`Segmentation fault (core dumped)` 段错误
又弄不好了
python 里是这样的
```
evaluator = Evaluator(context)
...
x_encrypted = Ciphertext()
...
x_sq_plus_one = Ciphertext()
evaluator.square(x_encrypted, x_sq_plus_one)
```
wrapper.cpp 中是
```
py::class_<Evaluator>(m, "Evaluator")
.def("square", (void (Evaluator::*)(const Ciphertext &, Ciphertext &)) &Evaluator::square)
```
怎么调试都是`Segmentation fault (core dumped)`
能提供一些意见吗?
https://github.com/Huelse/pyseal/blob/master/pyseal/wrapper.cpp
谢谢!
wutiantong
2019-07-18 10:59:30 +08:00
@Huelse

x_encrypted = Ciphertext(context)
x_sq_plus_one = Ciphertext(context)

改成这样试试。
Huelse
2019-07-18 15:14:46 +08:00
@wutiantong
经测试还是不行的,
好在我发现了是 MemoryPoolHandle()的问题,只需要

pool = MemoryPoolHandle().New(False)
evaluator.square(x_encrypted, x_sq_plus_one, pool)

就可以了,不过还是谢谢您~
Huelse
2019-07-22 12:24:12 +08:00
@wutiantong #15
啊,再打扰下,这种 template 该怎么绑定呢?

我已包含#include <pybind11/complex.h>
```
template<typename T,
typename = std::enable_if_t<std::is_same<T, double>::value ||
std::is_same<T, std::complex<double>>::value>>
inline void decode(const Plaintext &plain, std::vector<T> &destination,
MemoryPoolHandle pool = MemoryManager::GetPool())
{
...
}
```

虽然我把 T 替换成 double 类型可以编译成功,但使用中,函数并不能对这个 vector 做出修改
``` error
.def("decode", (void (CKKSEncoder::*)(const Plaintext &, std::vector<double> &, MemoryPoolHandle)) &CKKSEncoder::decode)
```
谢谢!
wutiantong
2019-07-22 12:38:04 +08:00

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/582999

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX