ä»æ¥ã¯ãPythonãC ++ã«çµ±åãããšãããããã¯ã«è§ŠããããšæããŸãã
ããã¯ãã¹ãŠãåå2æã«å人ããé»è©±ãããããè² è·ãããã£ãŠããç¶æ ã§æ¬çªç°å¢ããããŸã...ããšäžå¹³ãèšã£ããšããããå§ãŸããŸãããäŒè©±ã®äžã§ãæ¬çªç°å¢ã®ã³ãŒãã¯ipyparallelïŒäžŠååæ£ã³ã³ãã¥ãŒãã£ã³ã°ãå¯èœã«ããPythonããã±ãŒãžïŒã䜿çšããŠã¢ãã«ãèšç®ããŠèšè¿°ãããŠããããšãããããŸããããªã³ã©ã€ã³ã§çµæãååŸããŸãã ipyparallelã®ã¢ãŒããã¯ãã£ãç解ããè² è·ãããã£ãç¶æ ã§ãããã¡ã€ãªã³ã°ãå®è¡ããããšã«ããŸããã
ãã®ããã±ãŒãžã®ãã¹ãŠã®ã¢ãžã¥ãŒã«ãå®å šã«èšèšãããŠããããšãããã«æããã«ãªããŸããããã»ãšãã©ã®æéã¯ãããã¯ãŒãã³ã°ãjson解æãããã³ãã®ä»ã®äžéã¢ã¯ã·ã§ã³ã«è²»ããããŠããŸãã
ipyparallelã®è©³çŽ°ãªèª¿æ»ã®çµæãã©ã€ãã©ãªå šäœã2ã€ã®çžäºäœçšããã¢ãžã¥ãŒã«ã§æ§æãããŠããããšãå€æããŸããã
- ã¿ã¹ã¯ã®å¶åŸ¡ãšã¹ã±ãžã¥ãŒãªã³ã°ãæ åœããIpcontrolerã
- ã³ãŒãã®å®è¡è ã§ãããšã³ãžã³ã
ãããã®ã¢ãžã¥ãŒã«ãpyzmqãä»ããŠçžäºäœçšãããšããåªããæ©èœãå€æããŸãããåªãããšã³ãžã³ã¢ãŒããã¯ãã£ã®ãããã§ããããã¯ãŒãã³ã°ã®å®è£ ãcppzmqäžã«æ§ç¯ããããœãªã¥ãŒã·ã§ã³ã«çœ®ãæããããšãã§ããŸããããã®çœ®ãæãã«ãããç¡éã®éçºç¯å²ãéãããŸãã察å¿ãããã®ã¯ãã¢ããªã±ãŒã·ã§ã³ã®C ++éšåã§èšè¿°ã§ããŸãã
ããã«ããããšã³ãžã³ããŒã«ã¯çè«çã«ã¯ããã«é«éã«ãªããŸããããã©ã€ãã©ãªãPythonã³ãŒãã«çµ±åããåé¡ã¯è§£æ±ºãããŸããã§ãããã©ã€ãã©ãªãçµ±åããããã«å€ãã®ããšãããªããã°ãªããªãå Žåããã®ãããªãœãªã¥ãŒã·ã§ã³ã¯éèŠããªããæ£ã«æ®ããŸããçŸåšã®ãšã³ãžã³ã³ãŒãããŒã¹ã«éçºããã€ãã£ãã«å®è£ ããæ¹æ³ã«ã€ããŠã¯ãçåãæ®ããŸããã
éçºã®å®¹æããC ++å ã§ã®ã¿API宣èšãPythonå ã§è¿œå ã®ã©ãããŒã䜿çšããªããã©ã€ãã©ãªã®å šæ©èœããã€ãã£ãã«äœ¿çšãããªã©ãã©ã®ã¢ãããŒããåãããç解ããããã®åççãªåºæºãå¿ èŠã§ããããããŠãPythonã§C ++ã³ãŒãããã©ãã°ãããã€ãã£ãã®ïŒãããŠããã§ã¯ãªãïŒæ¹æ³ã§æ··ä¹±ããªãããã«ãå°ã調æ»ãè¡ããŸããã2019幎ã®åãã«ãPythonãæ¡åŒµãã4ã€ã®äžè¬çãªæ¹æ³ãã€ã³ã¿ãŒãããäžã§èŠã€ãããŸããã
- Ctypes
- CFFI
- Cython
- CPython API
ãã¹ãŠã®çµ±åãªãã·ã§ã³ãæ€èšããŸããã
1.Ctypes
Ctypesã¯ãCã€ã³ã¿ãŒãã§ã€ã¹ããšã¯ã¹ããŒãããåçã©ã€ãã©ãªãããŒãã§ããããã«ããå€éšé¢æ°ã€ã³ã¿ãŒãã§ã€ã¹ã§ããããã䜿çšãããšãPythonã®Cã©ã€ãã©ãªïŒlibevãlibpqãªã©ïŒã䜿çšã§ããŸãã
ããšãã°ã次ã®ã€ã³ã¿ãŒãã§ã€ã¹ãåããC ++ã§èšè¿°ãããã©ã€ãã©ãªããããŸãã
extern "C"
{
Foo* Foo_new();
void Foo_bar(Foo* foo);
}
ã©ãããŒãäœæããŸãã
import ctypes
lib = ctypes.cdll.LoadLibrary('./libfoo.so')
class Foo:
def __init__(self) -> None:
super().__init__()
lib.Foo_new.argtypes = []
lib.Foo_new.restype = ctypes.c_void_p
lib.Foo_bar.argtypes = []
lib.Foo_bar.restype = ctypes.c_void_p
self.obj = lib.Foo_new()
def bar(self) -> None:
lib.Foo_bar(self.obj)
çµè«ãå°ãåºããŸãã
- ã€ã³ã¿ããªã¿APIãšå¯Ÿè©±ã§ããªããCtypesã¯ãPythonåŽã§Cã©ã€ãã©ãªãšå¯Ÿè©±ããæ¹æ³ã§ãããC / C ++ã³ãŒããPythonãšå¯Ÿè©±ããæ¹æ³ãæäŸããŠããŸããã
- Cã¹ã¿ã€ã«ã®ã€ã³ã¿ãŒãã§ã€ã¹ããšã¯ã¹ããŒãããŸããtypesã¯ãã®ã¹ã¿ã€ã«ã§ABIã©ã€ãã©ãªãšå¯Ÿè©±ã§ããŸãããä»ã®èšèªã¯Cã©ãããŒãä»ããŠãã®å€æ°ãé¢æ°ãã¡ãœããããšã¯ã¹ããŒãããå¿ èŠããããŸãã
- ã©ãããŒãäœæããå¿ èŠããããŸãããããã¯ãCãšã®ABIäºææ§ã®ããã«C ++ã³ãŒãåŽã§ãããã³å®åã³ãŒãã®éãæžããããã«PythonåŽã§äœæããå¿ èŠããããŸãã
typesã¯ç§ãã¡ã«é©ããŠããŸããã次ã®æ¹æ³ã§ããCFFIãè©ŠããŸãã
2. CFFI
CFFIã¯Ctypesã«äŒŒãŠããŸãããããã€ãã®è¿œå æ©èœããããŸããåãã©ã€ãã©ãªã䜿çšããäŸã瀺ããŸãããã
import cffi
ffi = cffi.FFI()
ffi.cdef("""
Foo* Foo_new();
void Foo_bar(Foo* foo);
""")
lib = ffi.dlopen("./libfoo.so")
class Foo:
def __init__(self) -> None:
super().__init__()
self.obj = lib.Foo_new()
def bar(self) -> None:
lib.Foo_bar(self.obj)
çµè«ãå°ãåºããŸã
ãCFFIã«ã¯ãã©ãããŒã«ã€ã³ã¿ãŒãã§ã€ã¹ã®å®çŸ©ãæ瀺ããå¿ èŠããããããã©ãããŒãå°ã倪ããªãããšãé€ããŠãåãæ¬ ç¹ããããŸããCFFIãé©åã§ã¯ãããŸããã次ã®æ¹æ³ã§ããCythonã«ç§»ããŸãããã
3. Cython
Cythonã¯ãC / C ++ãšPythonãçµã¿åãããŠæ¡åŒµæ©èœãèšè¿°ãããã®çµæãåçã©ã€ãã©ãªãšããŠããŒãã§ããããã«ãããµã/ã¡ã¿ããã°ã©ãã³ã°èšèªã§ããä»åã¯ãC ++ã§èšè¿°ãããã€ã³ã¿ãŒãã§ã€ã¹ãæã€ã©ã€ãã©ãªããããŸãã
#ifndef RECTANGLE_H
#define RECTANGLE_H
namespace shapes {
class Rectangle {
public:
int x0, y0, x1, y1;
Rectangle();
Rectangle(int x0, int y0, int x1, int y1);
~Rectangle();
int getArea();
void getSize(int* width, int* height);
void move(int dx, int dy);
};
}
#endif
次ã«ããã®ã€ã³ã¿ãŒãã§ã€ã¹ãCythonèšèªã§å®çŸ©ããŸãã
cdef extern from "Rectangle.cpp":
pass
# Declare the class with cdef
cdef extern from "Rectangle.h" namespace "shapes":
cdef cppclass Rectangle:
Rectangle() except +
Rectangle(int, int, int, int) except +
int x0, y0, x1, y1
int getArea()
void getSize(int* width, int* height)
void move(int, int)
ãããŠãããã«ã©ãããŒãæžããŸãïŒ
# distutils: language = c++
from Rectangle cimport Rectangle
cdef class PyRectangle:
cdef Rectangle c_rect
def __cinit__(self, int x0, int y0, int x1, int y1):
self.c_rect = Rectangle(x0, y0, x1, y1)
def get_area(self):
return self.c_rect.getArea()
def get_size(self):
cdef int width, height
self.c_rect.getSize(&width, &height)
return width, height
def move(self, dx, dy):
self.c_rect.move(dx, dy)
# Attribute access
@property
def x0(self):
return self.c_rect.x0
@x0.setter
def x0(self, x0):
self.c_rect.x0 = x0
# Attribute access
@property
def x1(self):
return self.c_rect.x1
@x1.setter
def x1(self, x1):
self.c_rect.x1 = x1
# Attribute access
@property
def y0(self):
return self.c_rect.y0
@y0.setter
def y0(self, y0):
self.c_rect.y0 = y0
# Attribute access
@property
def y1(self):
return self.c_rect.y1
@y1.setter
def y1(self, y1):
self.c_rect.y1 = y1
ããã§ãéåžžã®Pythonã³ãŒããããã®ã¯ã©ã¹ã䜿çšã§ããŸãã
import rect
x0, y0, x1, y1 = 1, 2, 3, 4
rect_obj = rect.PyRectangle(x0, y0, x1, y1)
print(dir(rect_obj))
çµè«ãå°ãåºããŸãã
- Cythonã䜿çšããå Žåã§ããC ++åŽã§ã©ãããŒã³ãŒããäœæããå¿ èŠããããŸãããCã¹ã¿ã€ã«ã®ã€ã³ã¿ãŒãã§ã€ã¹ããšã¯ã¹ããŒãããå¿ èŠã¯ãããŸããã
- ããªãã¯ãŸã éèš³ãšå¯Ÿè©±ããããšã¯ã§ããŸããã
æåŸã®æ¹æ³ã¯æ®ã£ãŠããŸã-CPythonAPIããã£ãŠã¿ãŸãã
4. CPython API
CPython API-C ++ã§Pythonã€ã³ã¿ãŒããªã¿ãŒã®ã¢ãžã¥ãŒã«ãéçºã§ããããã«ããAPIãæåã®çã¯ãCPythonAPIã®æäœã䟿å©ã«ããé«ã¬ãã«ã®C ++ã©ã€ãã©ãªã§ããpybind11ã§ãããã®å©ããåããŠãC ++ã§é¢æ°ãã¯ã©ã¹ãç°¡åã«ãšã¯ã¹ããŒãããPythonã¡ã¢ãªãšãã€ãã£ãã¡ã¢ãªã®éã§ããŒã¿ãå€æã§ããŸãã
ããã§ã¯ãåã®äŸã®ã³ãŒããååŸããŠãããã«ã©ãããŒãèšè¿°ããŸãããã
PYBIND11_MODULE(rect, m) {
py::class_<Rectangle>(m, "PyRectangle")
.def(py::init<>())
.def(py::init<int, int, int, int>())
.def("getArea", &Rectangle::getArea)
.def("getSize", [](Rectangle &rect) -> std::tuple<int, int> {
int width, height;
rect.getSize(&width, &height);
return std::make_tuple(width, height);
})
.def("move", &Rectangle::move)
.def_readwrite("x0", &Rectangle::x0)
.def_readwrite("x1", &Rectangle::x1)
.def_readwrite("y0", &Rectangle::y0)
.def_readwrite("y1", &Rectangle::y1);
}
ã©ãããŒãäœæããŸããããã€ããªã©ã€ãã©ãªã«ã³ã³ãã€ã«ããå¿ èŠããããŸãããã«ãã·ã¹ãã ãšããã±ãŒãžãããŒãžã£ãŒã®2ã€ãå¿ èŠã§ãããããã®ç®çã®ããã«ãããããCMakeãšConanãåãäžããŸãããã
Conanã§ã®ãã«ããæ©èœãããã«ã¯ãé©åãªæ¹æ³ã§Conanèªäœãã€ã³ã¹ããŒã«ããå¿ èŠããããŸãã
pip3 install conan cmake
è¿œå ã®ãªããžããªãç»é²ããŸãã
conan remote add bincrafters https://api.bintray.com/conan/bincrafters/public-conan
conan remote add cyberduckninja https://api.bintray.com/conan/cyberduckninja/conan
conanfile.txtãã¡ã€ã«ã§pybindã©ã€ãã©ãªã®ãããžã§ã¯ãã®äŸåé¢ä¿ã説æããŸãããã
[requires]
pybind11/2.3.0@conan/stable
[generators]
cmake
CMakeãã¡ã€ã«ãè¿œå ããŸããããConanãšã®çµ±åã«æ³šæããŠãã ãã-CMakeãå®è¡ããããšãconan installã³ãã³ããå®è¡ãããäŸåé¢ä¿ãã€ã³ã¹ããŒã«ãããäŸåé¢ä¿ããŒã¿ã䜿çšããŠCMakeå€æ°ãçæãããŸãã
cmake_minimum_required(VERSION 3.17)
set(project rectangle)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED YES)
set(CMAKE_CXX_EXTENSIONS OFF)
if (NOT EXISTS "${CMAKE_BINARY_DIR}/conan.cmake")
message(STATUS "Downloading conan.cmake from https://github.com/conan-io/cmake-conan")
file(DOWNLOAD "https://raw.githubusercontent.com/conan-io/cmake-conan/v0.15/conan.cmake" "${CMAKE_BINARY_DIR}/conan.cmake")
endif ()
set(CONAN_SYSTEM_INCLUDES "On")
include(${CMAKE_BINARY_DIR}/conan.cmake)
conan_cmake_run(
CONANFILE conanfile.txt
BASIC_SETUP
BUILD missing
NO_OUTPUT_DIRS
)
find_package(Python3 COMPONENTS Interpreter Development)
include_directories(${PYTHON_INCLUDE_DIRS})
include_directories(${Python3_INCLUDE_DIRS})
find_package(pybind11 REQUIRED)
pybind11_add_module(${PROJECT_NAME} main.cpp )
target_include_directories(
${PROJECT_NAME}
PRIVATE
${NUMPY_ROOT}/include
${PROJECT_SOURCE_DIR}/vendor/General_NetSDK_Eng_Linux64_IS_V3.051
${PROJECT_SOURCE_DIR}/vendor/ffmpeg4.2.1
)
target_link_libraries(
${PROJECT_NAME}
PRIVATE
${CONAN_LIBS}
)
ãã¹ãŠã®æºåãå®äºããŸãããåéããŸãããã
cmake . -DCMAKE_BUILD_TYPE=Release
cmake --build . --parallel 2
çµè«ãå°ãåºããŸãã
- ã¢ã»ã³ãã«ããããã€ããªã©ã€ãã©ãªãåãåããŸãããããã¯ãåŸã§Pythonã€ã³ã¿ãŒããªã¿ãŒã«ããŒãã§ããŸãã
- äžèšã®æ¹æ³ãšæ¯èŒããŠãã³ãŒããPythonã«ãšã¯ã¹ããŒãããã®ãã¯ããã«ç°¡åã«ãªããã©ããã³ã°ã³ãŒããããã³ã³ãã¯ãã«ãªããåãèšèªã§èšè¿°ãããããã«ãªããŸããã
cpython / pybind11ã®æ©èœã®1ã€ã¯ãC ++ã©ã³ã¿ã€ã äžã«pythonã©ã³ã¿ã€ã ããé¢æ°ãããŒããååŸããŸãã¯å®è¡ããããšã§ãããã®éãåæ§ã§ãã
ç°¡åãªäŸãèŠãŠã¿ãŸãããã
#include <pybind11/embed.h> //
namespace py = pybind11;
int main() {
py::scoped_interpreter guard{}; // python vm
py::print("Hello, World!"); // Hello, World!
}
pythonã€ã³ã¿ãŒããªã¿ãŒãC ++ã¢ããªã±ãŒã·ã§ã³ãšPythonã¢ãžã¥ãŒã«ãšã³ãžã³ã«åã蟌ãæ©èœãçµã¿åãããããšã§ãipyparallesãšã³ãžã³ã³ãŒããã³ã³ããŒãã³ãã®çœ®æãæããªããšããèå³æ·±ãã¢ãããŒããæãã€ããŸãããã¢ããªã±ãŒã·ã§ã³ã®å Žåãã©ã€ããµã€ã¯ã«ãšã€ãã³ããµã€ã¯ã«ãC ++ã³ãŒãã§å§ãŸãããã®åŸãPythonã€ã³ã¿ãŒããªã¿ãŒãåãããã»ã¹å ã§éå§ããã¢ãŒããã¯ãã£ãéžæããŸããã
ç解ããããã«ãç§ãã¡ã®ã¢ãããŒããã©ã®ããã«æ©èœããããèŠãŠã¿ãŸãããã
#include <pybind11/embed.h>
#include "pyrectangle.hpp" // ++ rectangle
using namespace py::literals;
// rectangle
constexpr static char init_script[] = R"__(
import sys
sys.modules['rect'] = rect
)__";
// rectangle
constexpr static char load_script[] = R"__(
import sys, os
from importlib import import_module
sys.path.insert(0, os.path.dirname(path))
module_name, _ = os.path.splitext(path)
import_module(os.path.basename(module_name))
)__";
int main() {
py::scoped_interpreter guard; //
py::module pyrectangle("rect");
add_pyrectangle(pyrectangle); //
py::exec(init_script, py::globals(), py::dict("rect"_a = pyrectangle)); // Python.
py::exec(load_script, py::globals(), py::dict("path"_a = "main.py")); // main.py
return 0;
}
äžèšã®äŸã§ã¯ãpyrectangleã¢ãžã¥ãŒã«ãPythonã€ã³ã¿ãŒããªã¿ãŒã«è»¢éãããrectãšããŠã€ã³ããŒãã§ããããã«ãªããŸãããã«ã¹ã¿ã ãã³ãŒãã§äœãå€æŽãããŠããªãããšãäŸãæããŠèª¬æããŸãããã
from pprint import pprint
from rect import PyRectangle
r = PyRectangle(0, 3, 5, 8)
pprint(r)
assert r.getArea() == 25
width, height = r.getSize()
assert width == 5 and height == 5
ãã®ã¢ãããŒãã¯ãé«ãæè»æ§ãšå€ãã®ã«ã¹ã¿ãã€ãºãã€ã³ããããã³Pythonã¡ã¢ãªãåæ³çã«ç®¡çããæ©èœãç¹åŸŽãšããŠããŸãããã ããåé¡ããããŸãããšã©ãŒã®ã³ã¹ãã¯ä»ã®ãªãã·ã§ã³ãããã¯ããã«é«ãããã®ãªã¹ã¯ã«æ³šæããå¿ èŠããããŸãã
ãããã£ãŠãctypesãšCFFIã¯ãCã¹ã¿ã€ã«ã®ã©ã€ãã©ãªã€ã³ã¿ãŒãã§ã€ã¹ããšã¯ã¹ããŒãããå¿ èŠãããããããŸãPythonåŽã§ã©ãããŒãèšè¿°ããæçµçã«ã¯åã蟌ã¿ãå¿ èŠãªå Žåã¯CPython APIã䜿çšããå¿ èŠããããããé©åã§ã¯ãããŸãããCythonã«ã¯èŒžåºäžã®æ¬ é¥ã¯ãããŸããããä»ã®ãã¹ãŠã®æ¬ é¥ã¯ä¿æãããŠããŸããPybind11ã¯ãC ++åŽã§ã®ã©ãããŒã®åã蟌ã¿ãšæžã蟌ã¿ã®ã¿ããµããŒãããŸãããŸããããŒã¿æ§é ãæäœããããPythonã®é¢æ°ãã¡ãœãããåŒã³åºãããããããã®åºç¯ãªæ©èœãåããŠããŸãããã®çµæãCPythonAPIã®é«ã¬ãã«ã®C ++ã©ãããŒãšããŠpybind11ã決å®ããŸããã
C ++ã¢ããªã±ãŒã·ã§ã³å ã§ã®embedpythonã®äœ¿çšãšãé«éããŒã¿è»¢éã®ããã®ã¢ãžã¥ãŒã«ã¡ã«ããºã ãçµã¿åãããipyparallelãšã³ãžã³ã®ã³ãŒãããŒã¹ãåå©çšããããšã§ãrocketjoe_engineãååŸããŸãããã¡ã«ããºã ã¯ãªãªãžãã«ãšåãã§ããããããã¯ãŒã¯ã€ã³ã¿ã©ã¯ã·ã§ã³ãjsonåŠçãããã³ãã®ä»ã®äžéã¢ã¯ã·ã§ã³ã®ãã£ã¹ããæžããããšã§ãããé«éã«åäœããŸããããã«ãããå人ã¯GitHubãããžã§ã¯ãã§æåã®ã¹ã¿ãŒãç²åŸãããããã¯ã·ã§ã³ã«è² è·ããããããšãã§ããŸãã
Conan, Russian Python Week C++, Python Conan .
Russian Python Week 4 â 14 17 . , Python: Python- . , Python.
.