การผูก Python โดยใช้ pybind11 กับ std::filesystem เป็นอาร์กิวเมนต์ของฟังก์ชันที่ให้ TypeError

ฉันมีคลาส Foo() และคลาส Foo() มีฟังก์ชันพร้อมการประกาศต่อไปนี้:

bool Foo::copyFile(const std::filesystem::path& src, const std::filesystem::path& dest)

ข้อกำหนดคือคลาส Foo ควรมีการเชื่อมโยง Python ฉันใช้ pybind11 เพื่อสร้างการผูก Python

ฉันได้เขียนสิ่งต่อไปนี้เพื่อสร้างการผูก Python:

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

namespace py = pybind11;

PYBIND11_MODULE(TestModule, m) {
     py::class_ <Foo>(m, "Foo")
        .def(py::init())
        .def("copyFile",&Foo::copyFile);
};

คอมไพล์นี้ตกลงและฉันสามารถสร้างไฟล์ Python Bindings pyd ได้ เมื่อฉันใช้การผูก Python สำหรับคลาส Foo โดยใช้:

from TestModule import Foo

f = Foo()
ret = f.copyFile("C:\Users\csaikia\Downloads\testfile_src", "C:\Users\csaikia\Downloads\testfile_dest")

มันให้ TypeError ฉันสงสัยว่ามีบางอย่างเกี่ยวข้องกับการรองรับ pybind11 สำหรับ std::filesystem ใน c++17 เนื่องจากฉันไม่เห็นว่าสิ่งนี้เกิดขึ้นกับฟังก์ชันอื่น ๆ ของคลาสที่มี std::string หรือ std::vector

ข้อผิดพลาดที่ฉันได้รับคือ:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: copyFile(): incompatible function arguments. The following argument types are supported:
    1. (self: TestModule.Foo, arg0: std::filesystem::path, arg1: std::filesystem::path) -> bool

Invoked with: <TestModule.Foo object at 0x0000000002A33ED8>,  'C:\\Users\\csaikia\\Downloads\\testfile_src', 'C:\\Users\\csaikia\\Downloads\\testfile_dest'

Did you forget to `#include <pybind11/stl.h>`? Or <pybind11/complex.h>,
<pybind11/functional.h>, <pybind11/chrono.h>, etc. Some automatic
conversions are optional and require extra headers to be included
when compiling your pybind11 module.

ฉันยังใหม่กับ pybind11 ใครสามารถช่วยได้โปรดช่วยฉันจะแก้ไขปัญหานี้ได้อย่างไร


person user304255    schedule 06.05.2019    source แหล่งที่มา


คำตอบ (2)


จากการสนทนาของฉันกับ pybind11 devs:

"Pybind ไม่รู้ว่าจะแปลง py::str เป็น std::filesystem::path ได้อย่างไร ไม่มีลูกล้อที่ใช้งานได้หรือไม่ได้ผูกคลาส std::filesystem::path ไว้

วิธีที่ง่ายที่สุดคือการไม่ผูก Foo::copyFile โดยตรง แทนที่จะผูกแลมบ์ดาที่ยอมรับ const Foo& และ const std::string& เป็นพารามิเตอร์ จากนั้นคุณสามารถส่ง std::string ไปยัง copyFile โดยที่คาดว่าจะเป็น std::filesystem::path โดยปล่อยให้การแปลงโดยนัยของ C++ เกิดขึ้น

คุณยังสามารถทำ py::class_<std::filesystem::path> และสร้างการเชื่อมโยงสำหรับตัวแปลง std::string จากนั้นใช้ py::implicitly_convertible เพื่อให้การสร้างโดยนัยของ C++ ทั้งหมดเกิดขึ้นบนฝั่งหลาม แต่... เฮ้อ งานมากเกินไป"

มันใช้งานได้อย่างมีเสน่ห์!

person user304255    schedule 06.05.2019

เพียงเพิ่มบรรทัดต่อไปนี้ในการผูกของคุณ (สมมติว่า py::module& m)

py::class_<std::filesystem::path>(m, "Path")
    .def(py::init<std::string>());
py::implicitly_convertible<std::string, std::filesystem::path>();

นี่เป็นแนวทางหลังที่อธิบายโดย @ user304255

person Alexandro Sánchez    schedule 21.04.2020