簡體   English   中英

使用pybind11的UnicodeDecodeError

[英]UnicodeDecodeError with pybind11

我試圖包裝一個返回字符串的類。

class SS {
  public:
    SS(const std::string& s) : data_(s.data()), size_(s.size()) {}

    // Return a pointer to the beginning of the referenced data
    const char* data() const { return data_; }

    const char* data_;
    size_t size_;
};

class PySS: public SS {
  public:
    PySS(const std::string &str): SS(str) {
      std::cout << "cons " << str << std::endl; #key1
      std::cout << "data " << SS::data() << std::endl; # key1

    }

    std::string data() {
      std::cout << "call data " << SS::data() << std::endl; # p��
      return std::string(SS::data());
    }
};

void init_slice(py::module & m) {
  py::class_<PySS>(m, "SS")
    .def(py::init<const std::string&>())
    .def("data", &PySS::data);
}

從python調用時,

s = SS('key1')
print (s.data())

它會引發unicode錯誤

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xae in position 1: invalid start byte

我在構造函數中打印字符串,它顯示相同的結果。 但在另一個函數中,它顯示了一些未解釋的字符串。

任何想法?

[編輯]

以下是重現類似問題的最小示例。

class SS {
  public:
    SS(const std::string& s) : data_(s.data()) {}

    // Return a pointer to the beginning of the referenced data
    const char* data() const { return data_; }
    const std::string ToString() const {
      std::cout << std::string(data_) << std::endl;
      return std::string(data_);
    }

    const char* data_;
};

void init_slice(py::module & m) {
  py::class_<SS>(m, "Slice")
  .def(py::init<const std::string&>())
  .def("data", &SS::ToString);
}

問題方案

你的例子有幾個問題,最重要的是你的指針無效,因為它們指的是超出范圍的東西(你s class SS s參數)。

解決方案是將s復制到class SS的成員變量,如下所示:

#include <string>
#include <iostream>
#include <pybind11/pybind11.h>

namespace py = pybind11;

class SS {
  public:
    SS(const std::string& s) : m_data(s) {}

    const char* data() const { return m_data.data(); }

    std::string m_data;
};

class PySS: public SS {
  public:
    PySS(const std::string& s): SS(s) {}

    std::string get() { return std::string(SS::data()); }
};

PYBIND11_MODULE(example, m)
{
  py::class_<PySS>(m, "SS")
    .def(py::init<const std::string&>())
    .def("get", &PySS::get);
}

還有兩個評論:

  • 在您的示例中,缺少宏PYBIND11_MODULE ,它會處理一些能夠導入模塊的常規事項(請參閱此示例 )。
  • 我永遠不會用兩個不同的含義聲明相同的函數:你的SS::data()返回一個指針,而PySS::data()返回一個副本(一個std::string )。 因此我將后者重命名為PySS::get()以區分清楚。

解決第三方課程

鑒於你在你控制之外對class SS ,我認為你只能通過包裝解決問題。 例如:

#include <string>
#include <iostream>
#include <pybind11/pybind11.h>

namespace py = pybind11;

class SS {
  public:
    SS() = default;
    SS(const std::string& s) : data_(s.data()), size_(s.size()) {}
    const char* data() const { return data_; }

  private:
    const char* data_;
    size_t size_;
};

class PySS {
  public:
    PySS(const std::string& s) { m_data = s; m_SS = SS(m_data); }
    std::string get() { return std::string(m_SS.data()); }

  private:
    std::string m_data;
    SS m_SS;
};

PYBIND11_MODULE(example, m)
{
  py::class_<PySS>(m, "SS")
    .def(py::init<const std::string&>())
    .def("get", &PySS::get);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM