PyBind11 生成 pyd 文件,没有我定义的任何类

问题描述 投票:0回答:1

我正在使用 Pybind11 包装 C++ 类,以使其可以在 Python 中访问。我的项目涉及一个用Qt6构建的动态库,其中包含一个名为Package的类。我正在编写一个名为 PackageExt 的包装器类,并使用 Pybind11 将此包装器绑定到 Python 模块。以下是我正在使用的代码:

C++ 包装头 (packageext.h)

#ifndef PACKAGEEXT_H
#define PACKAGEEXT_H

#include "package.h" // from the dynamic library

class PackageExt {
public:
    PackageExt(const std::string &id);
    PackageExt(const ContainerCore::Package &pkg);
    PackageExt(const PackageExt &other);
    PackageExt& operator=(const PackageExt &other);
    ~PackageExt();
    void setPackageID(const std::string &id);
    std::string packageID() const;
    ContainerCore::Package* getBasePackage();
private:
    ContainerCore::Package *mPackage; // Defined in the dynamic library
};

#endif // PACKAGEEXT_H

Pybind11 绑定(bindcontainer.cpp)

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

namespace py = pybind11;

PYBIND11_MODULE(ContainerPy, m) {
    m.doc() = "Pybind11 plugin for Container library";

    py::class_<PackageExt>(m, "Package")
        .def(py::init<const std::string &>(), py::arg("id"),
             "Constructor that initializes a Package with the specified ID.")
        .def("get_package_id", &PackageExt::packageID,
             "Get the package ID as std::string.")
        .def("set_package_id", &PackageExt::setPackageID, py::arg("id"),
             "Set the package ID using std::string.");
}

CMake 配置(CMakeLists.txt)

find_package(Python REQUIRED COMPONENTS Interpreter Development)
find_package(QT NAMES Qt6 REQUIRED COMPONENTS Core Concurrent Xml Network Sql)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Concurrent Xml Network Sql)
find_package(pybind11 REQUIRED CONFIG HINTS ${PYBIND11_HINTS_PATH})
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(BINDING_FILES
    bindcontainer.cpp
    containerext.cpp
    packageext.cpp
    containermapext.cpp
)
pybind11_add_module(${PYTHON_LIB_NAME} MODULE ${BINDING_FILES})
target_link_libraries(${PYTHON_LIB_NAME} PRIVATE Container) # Dynamic library
target_link_libraries(${PYTHON_LIB_NAME} PRIVATE Qt6::Core Qt6::Concurrent Qt6::Network Qt6::Xml Qt6::Sql)
target_link_libraries(${PYTHON_LIB_NAME} PRIVATE Python::Python)

问题: 构建模块后,我成功获得了 .pyd 文件。但是,当我在 Python 中导入模块并检查它时,我看到以下内容:

蟒蛇

import ContainerPy
print(dir(ContainerPy))
The output is:
['__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__']

Package 类及其方法似乎没有按预期公开。可能是什么原因导致此问题?如何排除故障或修复它?

其他详细信息:

  • 我使用 Qt6 和 pybind11 来包装 C++ 类。
  • 动态库已正确链接,并且没有构建错误。
  • 我的环境配置为使用 CMake 来构建项目。
  • 我已经验证正在生成 .pyd 文件,但类绑定在 Python 中似乎不可见。
  • pyd 文件 ContainerPy/ContainerPy.cpython-313-x86_64-linux-gnu.so 安装在我的 python 环境中的 site-packages 文件夹中。
  • 我正在 Linux 上构建它,但代码也应该可以在 Windows/Macos 上构建。

我尝试过的:

  • 我确保 CMake 配置链接到所需的 Qt6 和 Python 组件。
  • 我验证了所有源文件都包含在 BINDING_FILES 列表中。
  • 我检查了是否存在任何可能导致类绑定不出现的缺失依赖项。

问题:

  • 我设置 Pybind11 绑定的方式是否存在问题?
  • 我应该检查 CMake 配置或库的链接方式吗?
python c++ pybind11
1个回答
0
投票

我遇到了一个问题,尽管正确生成了

.pyd
文件,但我的 C++ 类的 Pybind11 绑定在 Python 中不可见。在确保所有配置正确并在社区的帮助下进行故障排除后,解决方案出奇地简单。

问题:

.pyd
文件虽然位于正确的
site-packages
目录中,但 Python 无法正确识别。这是由于 Python 将目录视为潜在的包。

操作系统:Ubuntu 解决方案: 通过将

__init__.py
文件添加到包含
.pyd
文件的目录中解决了该问题。我添加了以下导入声明来阐明目的:

from .ContainerPy import *
© www.soinside.com 2019 - 2024. All rights reserved.