4

それ自体がスマート ポインターにラップされている STL コンテナーを返す C++ 関数 (Pybind11 を使用) をラップしようとしています。以下に例を示します。関数はオーバーロードされているため、署名を指定する必要があります。

#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include "my_class.h"

typedef std::array<std::complex<double>, 4> ArrayComplex4;
PYBIND11_MAKE_OPAQUE(ArrayComplex4);

namespace py = pybind11;
using namespace my_namespace;

PYBIND11_MODULE(my_module, m) {
    py::class_<MyClass>(m, "MyClass", py::dynamic_attr())
        .def("my_function", (std::unique_ptr<ArrayComplex4> (MyClass::*)(double)) &MyClass::my_function)
        .def("my_function", (std::unique_ptr<ArrayComplex4> (MyClass::*)(double, double)) &MyClass::my_function);
}

モジュールはコンパイルされますが、Python で関数を使用しようとするとエラーが発生します。

TypeError: 関数の戻り値を Python 型に変換できません!

Pybind11の設定が間違っているだけだと確信しています。助けてくれてありがとう!

編集

std::Array問題は間違いなく、データ型をバインドしようとしたことにありました。使用するコードを変更したところstd::Vector、Pybind11 には問題がありませんでした。std::Arrayコンテナをバインドする方法については、以下の AS Mackey の回答を参照してください。

4

1 に答える 1

7

問題は、ArrayComplex4 データ構造の PYBIND11_MAKE_OPAQUE 処理にある可能性があります。これを機能させることができませんでしたが、時間があればもう少し詳しく調べます。

私が実際に作業した次のコードは、これまでのところあなたの設計に最も近いものです。std:: 要素をラップするために、追加のユーザー定義データ構造を使用しました。

#include <pybind11/pybind11.h>
#include <pybind11/complex.h>
#include <pybind11/stl.h>
#include <memory>
#include <complex>
#include <array>
#include <cmath>

namespace py = pybind11;


typedef std::array<std::complex<double>, 4> ArrayComplex4;

struct ArrayComplex4Holder
{
    ArrayComplex4 data;
    ArrayComplex4 getData() { return data; }
};

class MyClass {
public:
    MyClass() { }
    std::unique_ptr<ArrayComplex4Holder> my_function(double x)
    {
        std::unique_ptr<ArrayComplex4Holder> ph( new ArrayComplex4Holder());
        ph->data[0] = std::complex<double>(x);
        return ph;
    }
    std::unique_ptr<ArrayComplex4Holder> my_function(double x, double y)
    {
        std::unique_ptr<ArrayComplex4Holder> ph( new ArrayComplex4Holder());
        ph->data[0] = std::complex<double>(x);
        ph->data[1] = std::complex<double>(y);
        return ph;
    }
};

PYBIND11_MODULE(example, m) {
    m.doc() = "pybind11 example"; // optional module docstring

    py::class_<ArrayComplex4Holder>(m, "ArrayComplex4Holder")
            .def(py::init<>())
            .def("getData", &ArrayComplex4Holder::getData);

    py::class_<MyClass>(m, "MyClass")
            .def(py::init<>())
            .def("my_function", (std::unique_ptr<ArrayComplex4Holder> (MyClass::*)(double))         &MyClass::my_function)
            .def("my_function", (std::unique_ptr<ArrayComplex4Holder> (MyClass::*)(double, double)) &MyClass::my_function);
}

NB Python キャスティングを機能させるには、追加の pybind #includes が必要であることがわかりました。

簡単な python コードは次のとおりです。

import sys
sys.path.append('/Volumes/RAID 1/Projects/workspace/Project CPP 1')
import example

p = example.MyClass()
print (p.my_function(1.2345).getData())
print (p.my_function(1.2345, 6.7890).getData())

これにより、正しいように見える次の出力が生成されます。

[(1.2345+0j), 0j, 0j, 0j]
[(1.2345+0j), (6.789+0j), 0j, 0j]

これがあなたの仕事の出発点になれば幸いです。あなたがより良い代替案を見つけたら、私は知りたいと思います...よろしく、AS

于 2017-09-02T14:49:02.547 に答える