Python调用C++

Python调用C++

前言

  最近研究Python调用C++开发的模块,尝试可行的方案有pybind11,cython,boost.python,swig,下面一一列举用法

环境准备

  • MacOS
  • Python3
  • python模块pybind11/cython
  • boost/swig
pip3 install pybind11 cython --user
brew install boost swig

pybind11

编写C++代码

// test.cpp
#include <iostream>
#include <pybind11/pybind11.h>
namespace py = pybind11;
PYBIND11_MODULE(testpybind11, m) {
    m.doc() = "pybind11 example plugin"; // 导出函数cpp_function
    m.def("cpp_function", [](const std::string& s1) {
        std::cout << s1 << std::endl;
        return s1;
    });
}
// 

编译兼容模块

c++ -O3 -Wall -shared -std=c++11 -undefined dynamic_lookup $(python3 -m pybind11 --includes) -DPYBIND11 test.cpp -o testpybind11$(python3-config --extension-suffix)
# 笔者Mac上生成testpybind11.cpython-39-darwin.so

python测试

import testpybind11
out = testpybind11.cpp_function("hello")
print(out)

cython

编写C++及接口代码

// test.cpp
#define EXPORT __attribute__ ((visibility("default")))
#include <iostream>
EXPORT std::string testcython(const std::string& s1) {
    std::cout << s1 << std::endl;
    return s1;
}

// testcython.pyx
from libcpp.string cimport string

cdef extern from "test.cpp":
    string testcython(const string& s1)
def pytestcython(const string& s1):
    return testcython(s1)

编译兼容模块

cython --cplus testcython.pyx -o test_wrapper.cpp
c++ -O3 -Wall -shared -std=c++11 -undefined dynamic_lookup $(python3 -m pybind11 --includes) -DPYTHON test_wrapper.cpp -o testcython$(python3-config --extension-suffix)

python测试

import testcython
input_str = "hello"
out = testcython.pytestcython(input_str.encode())
output_str = out.decode()
print(output_str)

boost.python

编写C++代码

// test.cpp
#include <iostream>
#include <boost/python.hpp>
std::string testpyboost(const std::string& s1) {
    std::cout << s1 << std::endl;
    return s1;
}
BOOST_PYTHON_MODULE(testpyboost)
{
    boost::python::def("cpp_function", testpyboost);
}

编译兼容模块

c++ -O3 -Wall -shared -std=c++11 -undefined dynamic_lookup $(python3 -m pybind11 --includes) -DPYBOOST test.cpp -o testpyboost$(python3-config --extension-suffix)

python测试

import testpyboost
out = testpyboost.cpp_function("hello")
print(out)

swig

编写C++及接口代码

// test.cpp
#define EXPORT __attribute__ ((visibility("default")))
#include <iostream>
EXPORT std::string pytestswig(const std::string& s1) {
    std::cout << s1 << std::endl;
    return s1;
}

// test.i
%module testswig
%include  "std_string.i"
%{
    std::string pytestswig(const std::string& s1);
%}
std::string pytestswig(const std::string& s1);

编译兼容模块

swig -python -c++ test.i
c++ -O3 -Wall -shared -undefined dynamic_lookup $(python3 -m pybind11 --includes) test_wrap.cxx test.cpp -o _testswig$(python3-config --extension-suffix)

python测试

import testswig
out = testswig.pytestswig("hello")
print(out)