前言
在C++代码中, 类(class)的使用频率非常高, 类将数据和对数据的操作方法封装在一起,使得代码的抽象层次增加。如何将C++中定义好的类在python中调用?下面举例简单说明。
开发/测试环境
- windows 10, 64bit
- Anaconda3, with python 3.7
- pycharm
- visaul studio 2017
示例一
定义一个简单的类
class Student {
public:
std::string name;
std::string gender;
int age;
public:
Student() {}
Student(std::string name, std::string gender, int age) {
this->name = name;
this->gender = gender;
this->age = age;
}
~Student() {};
public:
//setter
void setName(std::string name) {
this->name = name;
}
void setGender(std::string gender) {
this->gender = gender;
}
void setAge(int age) {
this->age = age;
}
//getter
std::string getName() {
return this->name;
}
std::string getGender() {
return this->gender;
}
int getAge() {
return this->age;
}
};
编写python扩展
PYBIND11_MODULE(example, m) {
// Studnet
py::class_<Student>(m, "Student")
.def(py::init<std::string, std::string, int>())
.def("setName", &Student::setName)
.def("setGender", &Student::setGender)
.def("setAge", &Student::setAge)
.def("getName", &Student::getName)
.def("getGender", &Student::getGender)
.def("getAge", &Student::getAge);
}
编译生成python扩展
测试代码
静态方法
代码
class Student {
public:
std::string name;
std::string gender;
int age;
public:
Student() {}
Student(std::string name, std::string gender, int age) {
this->name = name;
this->gender = gender;
this->age = age;
}
~Student() {};
public:
//setter
void setName(std::string name) {
this->name = name;
}
void setGender(std::string gender) {
this->gender = gender;
}
void setAge(int age) {
this->age = age;
}
//getter
std::string getName() {
return this->name;
}
std::string getGender() {
return this->gender;
}
int getAge() {
return this->age;
}
public:
//声明静态成员
static std::string university;
// static method
static std::string getUniversity() {
return university;
}
};
// 定义并且初始化static变量
std::string Student::university = "Xidian University";
PYBIND11_MODULE(example, m) {
//py::class_<Pet>(m, "Pet")
// .def(py::init<const std::string &>())
// .def("setName", &Pet::setName)
// .def("getName", &Pet::getName);
// Studnet
py::class_<Student>(m, "Student")
.def(py::init<std::string, std::string, int>())
.def("setName", &Student::setName)
.def("setGender", &Student::setGender)
.def("setAge", &Student::setAge)
.def("getName", &Student::getName)
.def("getGender", &Student::getGender)
.def("getAge", &Student::getAge)
.def_static("getUniversity", &Student::getUniversity); //def_static() 静态方法
}
例子2
定义一个Person类, 包含:
- 无参构造函数
- 含参构造函数
- private成员变量
- public成员变量
- static静态成员变量
- static静态函数
- setter/getter函数
class Person
{
public:
std::string habbit; //兴趣爱好
private:
std::string name; //姓名
std::string gender; //性别
int age; //年龄
std::string idCardNum; //身份证号码
std::string address; //住址
public:
void setName(std::string name) {
this->name = name;
}
void setAge(int age) {
this->age = age;
}
void setGender(std::string gender) {
this->gender = gender;
}
void setAddress(std::string address) {
this->address = address;
}
void setIdCardNum(std::string idCardNum) {
this->idCardNum = idCardNum;
}
std::string getName() {
return this->name;
}
std::string getGender() {
return this->gender;
}
int getAge() {
return this->age;
}
std::string getAddress() {
return this->address;
}
std::string getIdCardNum() {
return this->idCardNum;
}
public:
//
static std::string university;
static std::string getUniversity() {
return university;
}
public:
Person() {};
Person(std::string name, std::string gender, int age) {
this->name = name;
this->gender = gender;
this->age = age;
}
~Person() {};
};
std::string Person::university = "xidian University";
python扩展代码
def(py::init()) python中构造方法,无参数
.def(py::init<std::string, std::string, int>()) 构造方法,含参数
.def("setName", &Person::setName) set()方法
.def("getName", &Person::getName) get()方法
.def_static("getUniversity", &Person::getUniversity) static静态方法
.def_readonly_static("university", &Person::university) static静态只读成员
.def_readwrite("habbit", &Person::habbit) 可读可写成员
对于C++ class中private成员:
.def_property("name", &Person::getName, &Person::setName)
.def_property("age", &Person::getAge, &Person::setAge)
.def_property("gender", &Person::getGender, &Person::setGender)
.def_property("address", &Person::getAddress, &Person::setAddress)
.def_property("idCardNum", &Person::getIdCardNum, &Person::setIdCardNum);
完整代码
#include<iostream>
#include<pybind11/pybind11.h>
namespace py = pybind11;
class Person
{
public:
std::string habbit; //兴趣爱好
private:
std::string name; //姓名
std::string gender; //性别
int age; //年龄
std::string idCardNum; //身份证号码
std::string address; //住址
public:
void setName(std::string name) {
this->name = name;
}
void setAge(int age) {
this->age = age;
}
void setGender(std::string gender) {
this->gender = gender;
}
void setAddress(std::string address) {
this->address = address;
}
void setIdCardNum(std::string idCardNum) {
this->idCardNum = idCardNum;
}
std::string getName() {
return this->name;
}
std::string getGender() {
return this->gender;
}
int getAge() {
return this->age;
}
std::string getAddress() {
return this->address;
}
std::string getIdCardNum() {
return this->idCardNum;
}
public:
//
static std::string university;
static std::string getUniversity() {
return university;
}
public:
Person() {};
Person(std::string name, std::string gender, int age) {
this->name = name;
this->gender = gender;
this->age = age;
}
~Person() {};
};
std::string Person::university = "xidian University";
PYBIND11_MODULE(demo3, m) {
m.doc() = "Simple Class";
py::class_<Person>(m, "Person")
.def(py::init())
.def(py::init<std::string, std::string, int>())
.def("setName", &Person::setName)
.def("setAge", &Person::setAge)
.def("setGender", &Person::setGender)
.def("setAddress", &Person::setAddress)
.def("getName", &Person::getName)
.def("getAge", &Person::getAge)
.def("getGender", &Person::getGender)
.def("getAddress", &Person::getAddress)
.def_static("getUniversity", &Person::getUniversity)
.def_readonly_static("university", &Person::university)
.def_readwrite("habbit", &Person::habbit)
.def_property("name", &Person::getName, &Person::setName)
.def_property("age", &Person::getAge, &Person::setAge)
.def_property("gender", &Person::getGender, &Person::setGender)
.def_property("address", &Person::getAddress, &Person::setAddress)
.def_property("idCardNum", &Person::getIdCardNum, &Person::setIdCardNum);
}
在pycharm中测试
将vs生成的lib和pyd文件复制到python代码所在目录, 直接import即可:
python代码
person1 = demo3.Person()
person1.name = 'tianyu'
person1.age = 23
person1.gender = 'female'
print(person1.getName())
print(person1.getAge())
print(person1.getGender())
print(person1.university)
测试结果