首先,我对C++编程和pybind11相对陌生。下面的例子应该解释我的问题:
a.h
:
namespace test {
class A {
public:
static int something;
};
void setSomething(int input);
}
a.cpp
:
#include <pybind11/pybind11.h>
#include "a.h"
int test::A::something;
void test::setSomething(int input) {
A::something = input;
}
PYBIND11_MODULE(a, handle) {
handle.doc() = "I'm a docstring hehe";
handle.def("setSomething", &test::setSomething);
}
b.h
:
namespace test {
class B {
public:
B();
int getSomething() const;
};
}
b.cpp
:
#include <pybind11/pybind11.h>
#include "a.h"
#include "b.h"
namespace py = pybind11;
// int test::A::something;
test::B::B(){}
int test::B::getSomething() const {
return A::something;
}
PYBIND11_MODULE(b, handle) {
handle.doc() = "I'm a docstring hehe";
py::class_<test::B>(handle, "B")
.def(py::init())
.def("getSomething", &test::B::getSomething);
}
所以我有两个类A和B,它们在a.cpp
和b.cpp
中定义,都有头文件a.h
和b.h
。基本上,我试图访问B类中A类的静态变量。现在,如果我使用CMake编译它们并尝试运行test.py文件,我会得到一个ImportError
,告诉我undefined symbol: _ZN4test1A9somethingE
。我希望这不是一个愚蠢的问题。提前感谢您的帮助!
编辑:如果我在类内定义变量,它不会获取在类外之前或之后设置的值。
假设您已经使用上面的代码构建了两个模块。类似于a.so
和b.so
,您将使用单独的import a
和import b
语句将它们导入Python。
这是行不通的:您需要通过同一个二进制对象访问静态变量。即使链接正确,::test::A::something
在a.so
和b.so
中也会有不同的地址。(如果你使用的是pybind中的构建系统助手,你甚至不会注意到,因为当你导入两个模块时,"默认隐藏符号"将防止链接错误。(
您需要确保.cpp和b.cpp都链接到同一个库对象中。
在pybind中,PYBIND11_MODULE
的第一个参数等同于您正在构建的共享对象库。如果你想像这样模块化地排列你的软件,我建议在一个单独的源文件中定义pybind模块,然后将模块对象(你已经命名为handle
(传递给负责添加类绑定的函数。
示例:
module.cpp
PYBIND11_MODULE(m, handle) {
handle.doc() = "I'm a docstring hehe";
bind_a(handle);
bind_b(handle);
}
a.cpp
:
void bind_a(py::module& m) {
m.def("setSomething", &test::setSomething);
}
b.cpp
:
void bind_b(py::module& m) {
py::class_<test::B>(m, "B")
.def(py::init())
.def("getSomething", &test::B::getSomething);
}