zoukankan      html  css  js  c++  java
  • windows 10 上使用pybind11进行C++和Python代码相互调用 | Interfacing C++ and Python with pybind11 on windows 10

    本文首发于个人博客https://kezunlin.me/post/8b9c051d/,欢迎阅读!

    Interfacing C++ and Python with pybind11 on windows 10

    Series

    Guide

    requirements:

    • pybind11 v2.3.dev0
    • python 2.7

    install pytest

    pip install pytest 
    

    compile

    git clone https://github.com/pybind/pybind11.git
    cd pybind11
    mkdir build
    cd build
    cmake-gui ..
    

    with options

    PYBIND11_CPP_STANDARD /std:c++11 # default c++14
    PYTHON_EXECUTABLE C:/Python27/python.exe
    CMAKE_INSTALL_PREFIX C:/Program Files/pybind11
    

    compile with VS 2015 with x64 Release

    install to C:Program Filespybind11 with only include and share

    $ tree .
    
    .
    ├── include
    │   └── pybind11
    │       ├── attr.h
    │       ├── buffer_info.h
    │       ├── cast.h
    │       ├── chrono.h
    │       ├── common.h
    │       ├── complex.h
    │       ├── detail
    │       │   ├── class.h
    │       │   ├── common.h
    │       │   ├── descr.h
    │       │   ├── init.h
    │       │   ├── internals.h
    │       │   └── typeid.h
    │       ├── eigen.h
    │       ├── embed.h
    │       ├── eval.h
    │       ├── functional.h
    │       ├── iostream.h
    │       ├── numpy.h
    │       ├── operators.h
    │       ├── options.h
    │       ├── pybind11.h
    │       ├── pytypes.h
    │       ├── stl.h
    │       └── stl_bind.h
    └── share
        └── cmake
            └── pybind11
                ├── FindPythonLibsNew.cmake
                ├── pybind11Config.cmake
                ├── pybind11ConfigVersion.cmake
                ├── pybind11Targets.cmake
                └── pybind11Tools.cmake
    
    6 directories, 29 files
    

    Usage

    pybind11 (cpp--->python)

    • module: examplelib

    • target: examplelib

    • cpp: example.cpp

    example.cpp

    #include <pybind11/pybind11.h>
    
    namespace py = pybind11;
    
    int add(int i, int j) {
        return i + j;
    }
    
    /*
    #include <pybind11/pybind11.h>
    
    namespace py = pybind11;
    
    int add(int i, int j) {
        return i + j;
    }
    
    struct Pet {
    	Pet(const std::string &name) : name(name) { }
    	void setName(const std::string &name_) { name = name_; }
    	const std::string &getName() const { return name; }
    
    	std::string name;
    };
    
    
    /*
    module: examplelib 
    target: examplelib
    
    cpp: example.cpp
    */
    PYBIND11_MODULE(examplelib, m)
    {
    	// optional module docstring
    	m.doc() = "pybind11 example plugin";
    
    	// FUNCTIONS
    	// expose add function, and add keyword arguments and default arguments
    	m.def("add", &add, "A function which adds two numbers", py::arg("i") = 1, py::arg("j") = 2);
    
    	// DATA
    	// exporting variables
    	m.attr("the_answer") = 42;
    	py::object world = py::cast("World");
    	m.attr("what") = world;
    
    
    	// CLASSES
    	py::class_<Pet>(m, "Pet")
    		.def(py::init<const std::string &>())
    		.def("setName", &Pet::setName)
    		.def("getName", &Pet::getName);
    
    	/*
    	python3 
    	> help(examplelib)
    	*/
    }
    

    CMakeLists.txt

    cmake_minimum_required (VERSION 2.6)
    
    project (pybind)
    enable_language(C)
    enable_language(CXX)
    
    find_package(pybind11 CONFIG REQUIRED)
    include_directories(${pybind11_INCLUDE_DIRS})
    message([MAIN] "Found pybind11 v${pybind11_VERSION}: ${pybind11_INCLUDE_DIRS}")
    
    MESSAGE( [Main] " pybind11_INCLUDE_DIRS = ${pybind11_INCLUDE_DIRS}")
    MESSAGE( [Main] " pybind11_LIBRARIES = ${pybind11_LIBRARIES}")
    
    #
    #   # Create an extension module
    #   add_library(mylib MODULE main.cpp)
    #   target_link_libraries(mylib pybind11::module)
    #
    #   # Or embed the Python interpreter into an executable
    #   add_executable(myexe main.cpp)
    #   target_link_libraries(myexe pybind11::embed)
    
    # method (1): generate `examplelib.pyd`
    pybind11_add_module(examplelib example.cpp)
    
    # method (2): generate `examplelib.dll` rename to `examplelib.pyd`
    #add_library(examplelib MODULE example.cpp)
    #target_link_libraries(examplelib pybind11::module)
    
    MESSAGE( [Main] " pybind11_INCLUDE_DIRS = ${pybind11_INCLUDE_DIRS}")
    MESSAGE( [Main] " pybind11_LIBRARIES = ${pybind11_LIBRARIES}")
    
    #add_executable(cpp_use_python cpp_use_python.cpp)
    #target_link_libraries(cpp_use_python PRIVATE pybind11::embed)
    

    cmake and config
    cmake

    build with vs and we get 3 files:

    examplelib.lib 
    examplelib.exp
    examplelib.cp35-win_amd64.pyd
    

    python import examplelib

     python3
    Python 3.5.3 (v3.5.3:1880cb95a742, Jan 16 2017, 16:02:32) [MSC v.1900 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import examplelib
    >>> help(examplelib)
    Help on module examplelib:
    
    NAME
        examplelib - pybind11 example plugin
    
    CLASSES
        pybind11_builtins.pybind11_object(builtins.object)
            Pet
    
        class Pet(pybind11_builtins.pybind11_object)
         |  Method resolution order:
         |      Pet
         |      pybind11_builtins.pybind11_object
         |      builtins.object
         |
         |  Methods defined here:
         |
         |  __init__(...)
         |      __init__(self: examplelib.Pet, arg0: str) -> None
         |
         |  getName(...)
         |      getName(self: examplelib.Pet) -> str
         |
         |  setName(...)
         |      setName(self: examplelib.Pet, arg0: str) -> None
         |
         |  ----------------------------------------------------------------------
         |  Methods inherited from pybind11_builtins.pybind11_object:
         |
         |  __new__(*args, **kwargs) from pybind11_builtins.pybind11_type
         |      Create and return a new object.  See help(type) for accurate signature.
    
    FUNCTIONS
        add(...) method of builtins.PyCapsule instance
            add(i: int = 1, j: int = 2) -> int
    
            A function which adds two numbers
    
    DATA
        the_answer = 42
        what = 'World'
    
    FILE
        e:gitcarextrapybind11uild
    eleaseexamplelib.cp35-win_amd64.pyd
    
    
    >>> p = examplelib.Pet('kzl')
    >>> print(p)
    <examplelib.Pet object at 0x0000025EED9E3D18>
    >>> p.getName()
    'kzl'
    >>> examplelib.add(1,2)
    3
    >>> examplelib.the_answer
    42
    >>> examplelib.what
    'World'
    >>>
    

    embed

    example.py

    
    def add(i, j):
        print("hello, pybind11")
        return i+j
    
    class MyMath:
    
    	def __init__(self,name):
    		self.name = name
    		
    	def my_add(self,i,j):
    		return i + j
    	
    	def my_strcon(self,a,b):
    		return a + b
    

    cpp_use_python.cpp

    #include <pybind11/embed.h>  
    #include <iostream>  
    
    namespace py = pybind11;
    
    int main() {
    	py::scoped_interpreter python;
    
    	/*
    	import sys
    	print sys.path
    	print "Hello,World!"
    	*/
    	py::module sys = py::module::import("sys");
    	py::print(sys.attr("path"));
    	py::print("Hello, World!"); // use the Python API
    
    	/*
    	import example
    	n = example.add(1,2)
    	*/
    	py::module example = py::module::import("example");
    	py::object result = example.attr("add")(1, 2);
    	int n = result.cast<int>();
    	assert(n == 3);
    	std::cout << "result from example.add(1,2) = " << n << std::endl;
    
    	/*
    	from example import MyMath
    	obj = MyMath("v0")
    	obj.my_add(1,2)
    	*/
    	py::object MyMath = py::module::import("example").attr("MyMath"); // class
    	py::object obj = MyMath("v0"); // class object
    	py::object my_add = obj.attr("my_add");// object method
    	py::object result2 = my_add(1, 2); // result
    	int n2 = result2.cast<int>(); // cast from python type to c++ type
    	assert(n2 == 3);
    	std::cout << "result from obj.my_add(1,2) = " << n2 << std::endl;
    
    	/*
    	from example import MyMath
    	obj = MyMath("v0")
    	obj.my_strcon("abc","123");
    	*/
    
    	py::object my_strcon = obj.attr("my_strcon"); // object method
    	py::object result3 = my_strcon("abc", "123");
    	std::string str3 = result3.cast<std::string>();
    	std::cout << "result from obj.my_strcon(abc,123) = " << str3 << std::endl;
    
    	return 0;
    }
    

    CMakeLists.txt

    cmake_minimum_required (VERSION 2.6)
    
    project (pybind)
    enable_language(C)
    enable_language(CXX)
    
    find_package(pybind11 CONFIG REQUIRED)
    include_directories(${pybind11_INCLUDE_DIRS})
    
    MESSAGE( [Main] " pybind11_INCLUDE_DIRS = ${pybind11_INCLUDE_DIRS}")
    MESSAGE( [Main] " pybind11_LIBRARIES = ${pybind11_LIBRARIES}")
    
    add_executable(cpp_use_python cpp_use_python.cpp)
    target_link_libraries(cpp_use_python PRIVATE pybind11::embed)
    

    Reference

    History

    • 20180301: created.

    Copyright

  • 相关阅读:
    C#选择文件、选择文件夹、打开文件
    如何去掉数据库重复记录并且只保留一条记录
    SQL总结——存储过程
    SQL Server中的标识列
    c# 获取键盘的输入
    C# 中BindingSource 的用法
    WinForm timer 控件
    C#获得窗口控件句柄
    checkedListBox的使用
    c++从文件中读取特定字符串问题的总结
  • 原文地址:https://www.cnblogs.com/kezunlin/p/11841485.html
Copyright © 2011-2022 走看看