Última atualização:2026-10-12
Acelerando Python com pybind11¶
Normalmente, para operações demoradas, esperamos implementá-las em C++ e depois usar Python para chamar a interface correspondente; ou, por causa de uma biblioteca de baixo nível, é preciso oferecer uma API Python externa. Nesses casos, normalmente precisamos dar suporte ao acesso a C++ a partir de Python — como fazer isso?
Há vários métodos; nesta seção, tomando o pybind11 como exemplo, introduzimos um modelo completo de projeto: se você tiver esse tipo de necessidade mais adiante, pode modificá-lo a partir do modelo.
Nota: (versão para preguiçosos) todo o código desta seção também está na planeta.
1.Expansão da macro¶
Suponha: tomando como exemplo uma ordenação demorada, se quisermos escrever uma ordenação em C++ e depois usá-la em Python, como escrevê-la?
O programa C++ é bem simples: basta expor uma interface que faça a ordenação, por exemplo:
std::vector<int> sort_vector(const std::vector<int>& input) {
std::vector<int> result = input;
std::sort(result.begin(), result.end());
return result;
}
Basta usar a macro do pybind11 para definir um módulo, por exemplo:
PYBIND11_MODULE(sort_module, m) {
m.doc() = "pybind11 example plugin"; // Optional module docstring
m.def("sort_vector", &sort_vector, "A function that sorts a list of integers");
}
Quando fazemos import de uma biblioteca xxx em python, o interpretador Python, ao carregar um módulo de extensão escrito em C/C++, chama automaticamente uma função de entrada — e essa função de entrada é a PyInit_sort_module abaixo:
static ::pybind11::module_::module_def pybind11_module_def_sort_module [[maybe_unused]];
[[maybe_unused]] static void pybind11_init_sort_module(::pybind11::module_ &);
extern "C" [[maybe_unused]] __attribute__((visibility("default"))) PyObject *PyInit_sort_module();
extern "C" __attribute__((visibility("default"))) PyObject *PyInit_sort_module() {
{
const char *compiled_ver = "3" "." "11";
const char *runtime_ver = Py_GetVersion();
size_t len = std::strlen(compiled_ver);
if (std::strncmp(runtime_ver, compiled_ver, len) != 0 || (runtime_ver[len] >= '0' && runtime_ver[len] <= '9')) {
PyErr_Format(PyExc_ImportError,
"Python version mismatch: module was compiled for Python %s, "
"but the interpreter version is incompatible: %s.",
compiled_ver, runtime_ver);
return nullptr;
}
}
pybind11::detail::get_internals();
auto m = ::pybind11::module_::create_extension_module("sort_module", nullptr, &pybind11_module_def_sort_module);
try {
pybind11_init_sort_module(m);
return m.ptr();
} catch (pybind11::error_already_set & e) {
pybind11::raise_from(e, PyExc_ImportError, "initialization failed");
return nullptr;
} catch (const std::exception &e) {
::pybind11::set_error(PyExc_ImportError, e.what());
return nullptr;
}
}
void pybind11_init_sort_module(::pybind11::module_ & m) {
m.doc() = "pybind11 example plugin";
m.def("sort_vector", &sort_vector, "A function that sorts a list of integers");
}
>>> import sort_module
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: dynamic module does not define module export function (PyInit_sort_module)
2.CMake + pybind11¶
O uso do pybind11 em C++ é o seguinte:
- Arquivos de cabeçalho
Basta usar o módulo FetchContent, por exemplo:
Em seguida, adicione o seu módulo no CMakeLists: O cmake baixará o pybind11 para você e o compilará ao mesmo tempo.3.Uso¶
O acima gera um so, que é instalado no diretório site-packages do python e, assim, reconhecido no import; a seguir, demonstramos o nosso módulo personalizado:
import sort_module
def test_sort():
input_list = [5, 2, 3, 1, 4]
sorted_list = sort_module.sort_vector(input_list)
print(f"Original list: {input_list}")
print(f"Sorted list: {sorted_list}")
if __name__ == "__main__":
test_sort()
Tópicos relacionados¶
- Escrevendo C++ FnOnce à mão | C++那些事
- Pequeno projeto de gRPC em C++ | C++那些事
- Comunicação entre processos em C++ na prática | C++那些事
- Demo de serviço de URL curta em C++ | C++那些事
- C++17 e SQLite para medir o tamanho de diretórios | C++那些事
- Testes de performance com Google Benchmark | C++那些事
- Servidor HTTP com corrotinas do C++20 | C++那些事
- Serialização ZeroCopy com Protobuf | C++那些事
- Projeto de calculadora em pilha em C++ | C++那些事