Để dùng đối tượng Python trong C++, nhúng (embed) Python interpreter vào ứng dụng C++. Cách phổ biến: dùng Python C API hoặc tool như pybind11 (khuyên dùng hiện đại), Cython.
Ví dụ dùng Cython (như bài gốc)
File pycls.pyx – định nghĩa class Python và wrapper public:
class PyClass(object):
def __init__(self):
self.data = []
def add(self, val):
self.data.append(val)
def __str__(self):
return "Data: " + str(self.data)
cdef public object createPyClass():
return PyClass()
cdef public void addData(object p, int val):
p.add(val)
cdef public char* printCls(object p):
return bytes(str(p), encoding='utf-8')
Biên dịch: cython --cplus pycls.pyx → sinh pycls.cpp và pycls.h.
File main.cpp – nhúng Python và gọi:
#include <Python.h>
#include "pycls.h"
int main(int argc, char* argv[]) {
Py_Initialize(); // Khởi tạo Python interpreter
PyInit_pycls(); // Khởi tạo module (initpycls() trong Python 2)
PyObject* obj = createPyClass();
for (int i = 0; i < 10; ++i) {
addData(obj, i);
}
printf("%s\n", printCls(obj));
Py_Finalize(); // Dọn dẹp
return 0;
}
Biên dịch & link:
g++ pycls.cpp main.cpp -o app $(python3-config --cflags --ldflags) -std=c++17
Chạy: ./app → Data: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Cách hiện đại khuyên dùng: pybind11
pybind11 – Header-only library, dễ dùng, hiệu năng tốt, hỗ trợ C++11+.
// example.cpp
#include <pybind11/embed> // Embed Python
#include <pybind11/pybind11.h>
#include <iostream>
namespace py = pybind11;
int main() {
py::scoped_interpreter guard{}; // Khởi tạo & tự dọn dẹp (RAII)
py::object pyClass = py::module::import("my_module").attr("PyClass");
py::object obj = pyClass(); // Tạo instance
for (int i = 0; i < 10; ++i) {
obj.attr("add")(i); // Gọi method
}
std::cout << py::str(obj.attr("__str__")()) << std::endl;
return 0;
}
CMake: find_package(pybind11 REQUIRED) → target_link_libraries(app PRIVATE pybind11::embed).
So sánh
| Cách | Ưu điểm | Nhược điểm |
|---|---|---|
| Python C API (raw) | Không dependency, kiểm soát tối đa | Verbose, dễ leak refcount, error-prone |
| Cython | Tốc độ C, dễ viết extension module | Cần build step riêng, syntax hybrid |
| pybind11 (khuyên dùng) | Header-only, C++11 idiomatic, RAII, hỗ trợ STL↔Python container auto-convert | Cần C++11+, binary size lớn hơn chút |
| Boost.Python | Mature, strong | Heavy dependency, compile chậm |