Commit 38bd7113 authored by Wenzel Jakob's avatar Wenzel Jakob
Browse files

Initial commit

parents
CMakeCache.txt
CMakeFiles
Makefile
cmake_install.cmake
.DS_Store
/example/example.so
/example/example.pyd
*.sln
*.sdf
*.opensdf
*.vcxproj
*.filters
example.dir
Win32
x64
Release
Debug
.vs
CTestTestfile.cmake
Testing
# CMakeLists.txt -- Build system for the pybind11 examples
#
# Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
#
# All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
cmake_minimum_required(VERSION 2.8)
project(pybind)
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to 'MinSizeRel' as none was specified.")
set(CMAKE_BUILD_TYPE MinSizeRel CACHE STRING "Choose the type of build." FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release"
"MinSizeRel" "RelWithDebInfo")
endif()
set(Python_ADDITIONAL_VERSIONS 3.4 3.5 3.6)
find_package(PythonLibs 3 REQUIRED)
find_package(PythonInterp 3 REQUIRED)
string(TOUPPER "${CMAKE_BUILD_TYPE}" U_CMAKE_BUILD_TYPE)
if (UNIX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wno-unsequenced")
if (NOT ${U_CMAKE_BUILD_TYPE} MATCHES DEBUG)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
endif()
endif()
# Compile with compiler warnings turned on
if(MSVC)
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
endif()
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
endif()
include_directories(${PYTHON_INCLUDE_DIR} include)
add_library(example SHARED
include/pybind/cast.h
include/pybind/common.h
include/pybind/mpl.h
include/pybind/operators.h
include/pybind/pybind.h
include/pybind/pytypes.h
include/pybind/typeid.h
example/example.cpp
example/example1.cpp
example/example2.cpp
example/example3.cpp
example/example4.cpp
example/example5.cpp
example/example6.cpp
example/example7.cpp
example/example8.cpp
example/example9.cpp
)
set_target_properties(example PROPERTIES PREFIX "")
set_target_properties(example PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/example)
if (WIN32)
if (MSVC)
# Enforce size-based optimization and link time code generation on MSVC (~30% smaller binaries in experiments)
set_target_properties(example PROPERTIES COMPILE_FLAGS "/Os /GL")
set_target_properties(example PROPERTIES LINK_FLAGS "/LTCG")
endif()
# .PYD file extension on Windows
set_target_properties(example PROPERTIES SUFFIX ".pyd")
# Link against the Python shared library
target_link_libraries(example ${PYTHON_LIBRARY})
elseif (UNIX)
# It's quite common to have multiple copies of the same Python version
# installed on one's system. E.g.: one copy from the OS and another copy
# that's statically linked into an application like Blender or Maya.
# If we link our plugin library against the OS Python here and import it
# into Blender or Maya later on, this will cause segfaults when multiple
# conflicting Python instances are active at the same time.
# Windows does not seem to be affected by this issue. The solution for Linux
# and Mac OS is simple: we just don't link against the Python library. The
# resulting shared library will have missing symbols, but that's perfectly
# fine -- they will be resolved at import time.
# .SO file extension on Linux/Mac OS
set_target_properties(example PROPERTIES SUFFIX ".so")
# Strip unnecessary sections of the binary on Linux/Mac OS
if(APPLE)
set_target_properties(example PROPERTIES MACOSX_RPATH ".")
set_target_properties(example PROPERTIES LINK_FLAGS "-undefined dynamic_lookup -dead_strip")
if (NOT ${U_CMAKE_BUILD_TYPE} MATCHES DEBUG)
add_custom_command(TARGET example POST_BUILD COMMAND strip -u -r ${PROJECT_SOURCE_DIR}/example/example.so)
endif()
else()
if (NOT ${U_CMAKE_BUILD_TYPE} MATCHES DEBUG)
add_custom_command(TARGET example POST_BUILD COMMAND strip ${PROJECT_SOURCE_DIR}/example/example.so)
endif()
endif()
endif()
enable_testing()
set(RUN_TEST ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example/run_test.py)
foreach(i RANGE 1 7)
add_test(NAME example${i} COMMAND ${RUN_TEST} example${i})
endforeach()
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
# pybind11 -- Seamless operability between C++11 and Python
**pybind11** is a lightweight header library that exposes C++ types in Python
and vice versa, mainly to create Python bindings of existing C++ code. Its
goals and syntax are similar to the excellent
[Boost.Python](http://www.boost.org/doc/libs/1_58_0/libs/python/doc/) library
by David Abrahams: to minimize boilerplate code in traditional extension
modules by inferring type information using compile-time introspection.
The main issue with Boost.Python—and the reason for creating such a similar
project—is Boost. Boost is an enormously large and complex suite of utility
libraries that works with almost every C++ compiler in existence. This
compatibility has its cost: arcane template tricks and workarounds are
necessary to support the oldest and buggiest of compiler specimens. Now that
C++11-compatible compilers are widely available, this heavy machinery has
become an excessively large and unnecessary dependency.
Think of this library as a tiny self-contained version of Boost.Python with
everything stripped away that isn't relevant for binding generation. The whole
codebase requires less than 2000 lines of code and just depends on Python and
the C++ standard library. This compact implementation was possible thanks to
some of the new C++11 language features (tuples, lambda functions and variadic
templates), and by only targeting Python 3.x and higher.
## Core features
The following C++ features can be mapped to Python
- Functions accepting and returning custom data structures per value, reference, or pointer
- Instance methods and static methods
- Overloaded functions
- Instance attributes and static attributes
- Exceptions
- Enumerations
- Callbacks
- Custom operators
- STL data structures
- Smart pointers with reference counting like `std::shared_ptr`
- Internal references with correct reference counting
## Goodies
In addition to the core functionality, pybind11 provides some extra goodies:
- It's easy to expose the internal storage of custom data types through
Pythons' buffer protocols. This is handy e.g. for fast conversion between
C++ matrix classes like Eigen and NumPy without expensive copy operations.
- Python's slice-based access and assignment operations can be supported with
just a few lines of code.
- pybind11 uses C++11 move constructors and move assignment operators whenever
possible to efficiently transfer custom data types.
## Limitations
Various things that Boost.Python can do remain unsupported, e.g.:
- Fine grained exception translation: currently, all exceptions derived from
`std::exception` are mapped to a Python `Exception`, but that's it.
- Default arguments in C++ functions are ignored, though their effect can be
emulated by binding multiple overloads using anonymous functions.
- Python keyword arguments are not supported in bindings
- Weak pointers are not supported
## What does the binding code look like?
Here is a simple example. The directory `example` contains many more.
```C++
#include <pybind/pybind.h>
#include <pybind/operators.h>
namespace py = pybind;
/// Example C++ class which should be bound to Python
class Test {
public:
Test();
Test(int value);
std::string toString();
Test operator+(const Test &e) const;
void print_dict(py::dict dict) {
/* Easily interact with Python types */
for (auto item : dict)
std::cout << "key=" << item.first << ", "
<< "value=" << item.second << std::endl;
}
int value = 0;
};
PYTHON_PLUGIN(example) {
py::module m("example", "pybind example plugin");
py::class_<Test>(m, "Test", "docstring for the Test class")
.def(py::init<>(), "docstring for constructor 1")
.def(py::init<int>(), "docstring for constructor 2")
.def(py::self + py::self, "Addition operator")
.def("__str__", &Test::toString, "Convert to a string representation")
.def("print_dict", &Test::print_dict, "Print a Python dictionary")
.def_readwrite("value", &Test::value, "An instance attribute");
return m.ptr();
}
```
/*
example/example.cpp -- pybind example plugin
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
*/
#include "example.h"
void init_ex1(py::module &);
void init_ex2(py::module &);
void init_ex3(py::module &);
void init_ex4(py::module &);
void init_ex5(py::module &);
void init_ex6(py::module &);
void init_ex7(py::module &);
void init_ex8(py::module &);
void init_ex9(py::module &);
PYTHON_PLUGIN(example) {
py::module m("example", "pybind example plugin");
init_ex1(m);
init_ex2(m);
init_ex3(m);
init_ex4(m);
init_ex5(m);
init_ex6(m);
init_ex7(m);
init_ex8(m);
init_ex9(m);
return m.ptr();
}
#include <pybind/pybind.h>
#include <iostream>
using std::cout;
using std::endl;
namespace py = pybind;
/*
example/example1.cpp -- Example 1: constructors, deconstructors,
attribute access, __str__, argument and return value conventions
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
*/
#include "example.h"
class Example1 {
public:
Example1() {
cout << "Called Example1 default constructor.." << endl;
}
Example1(int value) : value(value) {
cout << "Called Example1 constructor with value " << value << ".." << endl;
}
Example1(const Example1 &e) : value(e.value) {
cout << "Called Example1 copy constructor with value " << value << ".." << endl;
}
Example1(Example1 &&e) : value(e.value) {
cout << "Called Example1 move constructor with value " << value << ".." << endl;
e.value = 0;
}
~Example1() {
cout << "Called Example1 destructor (" << value << ")" << endl;
}
std::string toString() {
return "Example1[value=" + std::to_string(value) + "]";
}
void operator=(const Example1 &e) { cout << "Assignment operator" << endl; value = e.value; }
void operator=(Example1 &&e) { cout << "Move assignment operator" << endl; value = e.value; e.value = 0;}
void add1(Example1 other) { value += other.value; } // passing py value
void add2(Example1 &other) { value += other.value; } // passing by reference
void add3(const Example1 &other) { value += other.value; } // passing by const reference
void add4(Example1 *other) { value += other->value; } // passing py pointer
void add5(const Example1 *other) { value += other->value; } // passing by const pointer
void add6(int other) { value += other; } // passing py value
void add7(int &other) { value += other; } // passing by reference
void add8(const int &other) { value += other; } // passing by const reference
void add9(int *other) { value += *other; } // passing py pointer
void add10(const int *other) { value += *other; } // passing by const pointer
Example1 self1() { return *this; } // return by value
Example1 &self2() { return *this; } // return by reference
const Example1 &self3() { return *this; } // return by const reference
Example1 *self4() { return this; } // return by pointer
const Example1 *self5() { return this; } // return by const pointer
int internal1() { return value; } // return by value
int &internal2() { return value; } // return by reference
const int &internal3() { return value; } // return by const reference
int *internal4() { return &value; } // return by pointer
const int *internal5() { return &value; } // return by const pointer
int value = 0;
};
void init_ex1(py::module &m) {
py::class_<Example1>(m, "Example1")
.def(py::init<>())
.def(py::init<int>())
.def(py::init<const Example1&>())
.def("add1", &Example1::add1)
.def("add2", &Example1::add2)
.def("add3", &Example1::add3)
.def("add4", &Example1::add4)
.def("add5", &Example1::add5)
.def("add6", &Example1::add6)
.def("add7", &Example1::add7)
.def("add8", &Example1::add8)
.def("add9", &Example1::add9)
.def("add10", &Example1::add10)
.def("self1", &Example1::self1)
.def("self2", &Example1::self2)
.def("self3", &Example1::self3)
.def("self4", &Example1::self4)
.def("self5", &Example1::self5)
.def("internal1", &Example1::internal1)
.def("internal2", &Example1::internal2)
.def("internal3", &Example1::internal3)
.def("internal4", &Example1::internal4)
.def("internal5", &Example1::internal5)
.def("__str__", &Example1::toString)
.def_readwrite("value", &Example1::value);
}
#!/usr/bin/env python3
import sys
sys.path.append('.')
from example import Example1
instance1 = Example1()
instance2 = Example1(32)
instance1.add1(instance2)
instance1.add2(instance2)
instance1.add3(instance2)
instance1.add4(instance2)
instance1.add5(instance2)
instance1.add6(32)
instance1.add7(32)
instance1.add8(32)
instance1.add9(32)
instance1.add10(32)
print("Instance 1: " + str(instance1))
print("Instance 2: " + str(instance2))
print(instance1.self1())
print(instance1.self2())
print(instance1.self3())
print(instance1.self4())
print(instance1.self5())
print(instance1.internal1())
print(instance1.internal2())
print(instance1.internal3())
print(instance1.internal4())
print(instance1.internal5())
print("Instance 1, direct access = %i" % instance1.value)
instance1.value = 100
print("Instance 1: " + str(instance1))
Called Example1 default constructor..
Called Example1 constructor with value 32..
Called Example1 copy constructor with value 32..
Called Example1 move constructor with value 32..
Called Example1 move constructor with value 32..
Called Example1 destructor (32)
Called Example1 destructor (0)
Called Example1 destructor (0)
Called Example1 copy constructor with value 320..
Called Example1 copy constructor with value 320..
Called Example1 destructor (320)
Called Example1 destructor (320)
Instance 1: Example1[value=320]
Instance 2: Example1[value=32]
Example1[value=320]
Example1[value=320]
Example1[value=320]
Example1[value=320]
Example1[value=320]
320
320
320
320
320
Instance 1, direct access = 320
Instance 1: Example1[value=100]
Called Example1 destructor (32)
Called Example1 destructor (100)
/*
example/example2.cpp2 -- Example 2: singleton design pattern, static
functions and variables, passing and interacting with Python types
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
*/
#include "example.h"
class Example2 {
public:
static Example2 *new_instance() {
return new Example2();
}
~Example2() {
std::cout << "Destructing Example2" << std::endl;
}
/* Create and return a Python dictionary */
py::dict get_dict() {
py::dict dict;
dict[py::str("key")] = py::str("value");
return dict;
}
/* Create and return a C++ dictionary */
std::map<std::string, std::string> get_dict_2() {
std::map<std::string, std::string> result;
result["key"] = "value";
return result;
}
/* Create, manipulate, and return a Python list */
py::list get_list() {
py::list list;
list.append(py::str("value"));
cout << "Entry at positon 0: " << py::object(list[0]) << endl;
list[0] = py::str("overwritten");
return list;
}
/* C++ STL data types are automatically casted */
std::vector<std::string> get_list_2() {
std::vector<std::string> list;
list.push_back("value");
return list;
}
/* Easily iterate over a dictionary using a C++11 range-based for loop */
void print_dict(py::dict dict) {
for (auto item : dict)
std::cout << "key: " << item.first << ", value=" << item.second << std::endl;
}
/* STL data types are automatically casted from Python */
void print_dict_2(const std::map<std::string, std::string> &dict) {
for (auto item : dict)
std::cout << "key: " << item.first << ", value=" << item.second << std::endl;
}
/* Easily iterate over a list using a C++11 range-based for loop */
void print_list(py::list list) {
int index = 0;
for (auto item : list)
std::cout << "list item " << index++ << ": " << item << std::endl;
}
/* STL data types are automatically casted from Python */
void print_list_2(std::vector<std::string> &list) {
int index = 0;
for (auto item : list)
std::cout << "list item " << index++ << ": " << item << std::endl;
}
/* pybind automatically translates between C++11 and Python tuples */
std::pair<std::string, bool> pair_passthrough(std::pair<bool, std::string> input) {
return std::make_pair(input.second, input.first);
}
/* pybind automatically translates between C++11 and Python tuples */
std::tuple<int, std::string, bool> tuple_passthrough(std::tuple<bool, std::string, int> input) {
return std::make_tuple(std::get<2>(input), std::get<1>(input), std::get<0>(input));
}
void throw_exception() {
throw std::runtime_error("This exception was intentionally thrown.");
}
static int value;
static const int value2;
};
int Example2::value = 0;
const int Example2::value2 = 5;
void init_ex2(py::module &m) {
/* No constructor is explicitly defined below. An exception is raised when
trying to construct it directly from Python */
py::class_<Example2>(m, "Example2")
.def("get_dict", &Example2::get_dict, "Return a Python dictionary")
.def("get_dict_2", &Example2::get_dict_2, "Return a C++ dictionary")
.def("get_list", &Example2::get_list, "Return a Python list")
.def("get_list_2", &Example2::get_list_2, "Return a C++ list")
.def("print_dict", &Example2::print_dict, "Print entries of a Python dictionary")
.def("print_dict_2", &Example2::print_dict_2, "Print entries of a C++ dictionary")
.def("print_list", &Example2::print_list, "Print entries of a Python list")
.def("print_list_2", &Example2::print_list_2, "Print entries of a C++ list")
.def("pair_passthrough", &Example2::pair_passthrough, "Return a pair in reversed order")
.def("tuple_passthrough", &Example2::tuple_passthrough, "Return a triple in reversed order")
.def("throw_exception", &Example2::throw_exception, "Throw an exception")
.def_static("new_instance", &Example2::new_instance, "Return an instance")
.def_readwrite_static("value", &Example2::value, "Static value member")
.def_readonly_static("value2", &Example2::value2, "Static value member (readonly)");
}
#!/usr/bin/env python3
import sys, pydoc
sys.path.append('.')
from example import Example2
Example2.value = 15
print(Example2.value)
print(Example2.value2)
try:
Example2()
except Exception as e:
print(e)
try:
Example2.value2 = 15
except Exception as e:
print(e)
instance = Example2.new_instance()
dict_result = instance.get_dict()
dict_result['key2'] = 'value2'
instance.print_dict(dict_result)
dict_result = instance.get_dict_2()
dict_result['key2'] = 'value2'
instance.print_dict_2(dict_result)
list_result = instance.get_list()
list_result.append('value2')
instance.print_list(list_result)
list_result = instance.get_list_2()
list_result.append('value2')
instance.print_list_2(list_result)
try:
instance.throw_exception()
except Exception as e:
print(e)
print(instance.pair_passthrough((True, "test")))
print(instance.tuple_passthrough((True, "test", 5)))
print(pydoc.render_doc(Example2, "Help on %s"))
key: key, value=value
key: key2, value=value2
key: key, value=value
key: key2, value=value2
Entry at positon 0: value
list item 0: overwritten
list item 1: value2
list item 0: value
list item 1: value2
15
5
example.Example2: No constructor defined!
can't set attribute
This exception was intentionally thrown.
('test', True)
(5, 'test', True)
Help on class Example2 in module example
class EExxaammppllee22(builtins.object)
| Methods defined here:
|
| ____iinniitt____(self, /, *args, **kwargs)
| Initialize self. See help(type(self)) for accurate signature.
|
| ____nneeww____ = <built-in method __new__ of example.Example2_meta object>
| ggeett__ddiicctt(...) from builtins.PyCapsule
| Signature : get_dict(Example2) -> dict
|
| Return a Python dictionary
|
| ggeett__ddiicctt__22(...) from builtins.PyCapsule
| Signature : get_dict_2(Example2) -> dict<str, str>
|
| Return a C++ dictionary
|
| ggeett__lliisstt(...) from builtins.PyCapsule
| Signature : get_list(Example2) -> list
|
| Return a Python list
|
| ggeett__lliisstt__22(...) from builtins.PyCapsule
| Signature : get_list_2(Example2) -> list<str>
|
| Return a C++ list
|
| nneeww__iinnssttaannccee(...) from builtins.PyCapsule
| Signature : new_instance() -> Example2
|
| Return an instance
|
| ppaaiirr__ppaasssstthhrroouugghh(...) from builtins.PyCapsule
| Signature : pair_passthrough(Example2, (bool, str)) -> (str, bool)
|
| Return a pair in reversed order
|
| pprriinntt__ddiicctt(...) from builtins.PyCapsule
| Signature : print_dict(Example2, dict) -> None
|
| Print entries of a Python dictionary
|
| pprriinntt__ddiicctt__22(...) from builtins.PyCapsule
| Signature : print_dict_2(Example2, dict<str, str>) -> None
|
| Print entries of a C++ dictionary
|
| pprriinntt__lliisstt(...) from builtins.PyCapsule
| Signature : print_list(Example2, list) -> None
|
| Print entries of a Python list
|
| pprriinntt__lliisstt__22(...) from builtins.PyCapsule
| Signature : print_list_2(Example2, list<str>) -> None
|
| Print entries of a C++ list
|
| tthhrrooww__eexxcceeppttiioonn(...) from builtins.PyCapsule
| Signature : throw_exception(Example2) -> None
|
| Throw an exception
|
| ttuuppllee__ppaasssstthhrroouugghh(...) from builtins.PyCapsule
| Signature : tuple_passthrough(Example2, (bool, str, int32_t)) -> (int32_t, str, bool)
|
| Return a triple in reversed order
|
| ----------------------------------------------------------------------
| Data and other attributes defined here:
|
| ____iinnssttaannccee__ssiizzee____ = 1
Destructing Example2
/*
example/example3.cpp -- Example 3: operator overloading
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
*/
#include "example.h"
#include <pybind/operators.h>
class Vector2 {
public:
Vector2(float x, float y) : x(x), y(y) { std::cout << "Value constructor" << std::endl; }
Vector2(const Vector2 &v) : x(v.x), y(v.y) { std::cout << "Copy constructor" << std::endl; }
Vector2(Vector2 &&v) : x(v.x), y(v.y) { std::cout << "Move constructor" << std::endl; v.x = v.y = 0; }
~Vector2() { std::cout << "Destructor." << std::endl; }
std::string toString() const {
return "[" + std::to_string(x) + ", " + std::to_string(y) + "]";
}
void operator=(const Vector2 &v) {
cout << "Assignment operator" << endl;
x = v.x;
y = v.y;
}
void operator=(Vector2 &&v) {
cout << "Move assignment operator" << endl;
x = v.x; y = v.y; v.x = v.y = 0;
}
Vector2 operator+(const Vector2 &v) const { return Vector2(x + v.x, y + v.y); }
Vector2 operator-(const Vector2 &v) const { return Vector2(x - v.x, y - v.y); }
Vector2 operator-(float value) const { return Vector2(x - value, y - value); }
Vector2 operator+(float value) const { return Vector2(x + value, y + value); }
Vector2 operator*(float value) const { return Vector2(x * value, y * value); }
Vector2 operator/(float value) const { return Vector2(x / value, y / value); }
Vector2& operator+=(const Vector2 &v) { x += v.x; y += v.y; return *this; }
Vector2& operator-=(const Vector2 &v) { x -= v.x; y -= v.y; return *this; }
Vector2& operator*=(float v) { x *= v; y *= v; return *this; }
Vector2& operator/=(float v) { x /= v; y /= v; return *this; }
private:
float x, y;
};
void init_ex3(py::module &m) {
py::class_<Vector2>(m, "Vector2")
.def(py::init<float, float>())
.def(py::self + py::self)
.def(py::self + float())
.def(py::self - py::self)
.def(py::self - float())
.def(py::self * float())
.def(py::self / float())
.def(py::self += py::self)
.def(py::self -= py::self)
.def(py::self *= float())
.def(py::self /= float())
.def("__str__", &Vector2::toString);
m.attr("Vector") = m.attr("Vector2");
}
#!/usr/bin/env python3
import sys
sys.path.append('.')
from example import Vector2, Vector
v1 = Vector2(1, 2)
v2 = Vector(3, -1)
print("v1 = " + str(v1))
print("v2 = " + str(v2))
print("v1+v2 = " + str(v1+v2))
print("v1-v2 = " + str(v1-v2))
print("v1-8 = " + str(v1-8))
print("v1+8 = " + str(v1+8))
print("v1*8 = " + str(v1*8))
print("v1/8 = " + str(v1/8))
v1 += v2
v1 *= 2
print("(v1+v2)*2 = " + str(v1))
Value constructor
Value constructor
Value constructor
Copy constructor
Destructor.
Destructor.
Value constructor
Copy constructor
Destructor.
Destructor.
Value constructor
Copy constructor
Destructor.
Destructor.
Value constructor
Copy constructor
Destructor.
Destructor.
Value constructor
Copy constructor
Destructor.
Destructor.
Value constructor
Copy constructor
Destructor.
Destructor.
v1 = [1.000000, 2.000000]
v2 = [3.000000, -1.000000]
v1+v2 = [4.000000, 1.000000]
v1-v2 = [-2.000000, 3.000000]
v1-8 = [-7.000000, -6.000000]
v1+8 = [9.000000, 10.000000]
v1*8 = [8.000000, 16.000000]
v1/8 = [0.125000, 0.250000]
(v1+v2)*2 = [8.000000, 2.000000]
Destructor.
Destructor.
/*
example/example4.cpp -- Example 4: global constants and functions, enumerations
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
*/
#include "example.h"
enum EMyEnumeration {
EFirstEntry = 1,
ESecondEntry
};
class Example4 {
public:
enum EMode {
EFirstMode = 1,
ESecondMode
};
static void test_function(EMode mode) {
std::cout << "Example4::test_function(enum=" << mode << ")" << std::endl;
}
};
bool test_function1() {
std::cout << "test_function()" << std::endl;
return false;
}
float test_function2(int i) {
std::cout << "test_function(" << i << ")" << std::endl;
return i / 2.f;
}
void test_function3(EMyEnumeration k) {
std::cout << "test_function(enum=" << k << ")" << std::endl;
}
void init_ex4(py::module &m) {
m.def("test_function", &test_function1);
m.def("test_function", &test_function2);
m.def("test_function", &test_function3);
m.attr("some_constant") = py::int_(14);
py::enum_<EMyEnumeration>(m, "EMyEnumeration")
.value("EFirstEntry", EFirstEntry)
.value("ESecondEntry", ESecondEntry)
.export_values();
py::class_<Example4> ex4_class(m, "Example4");
ex4_class.def_static("test_function", &Example4::test_function);
py::enum_<Example4::EMode>(ex4_class, "EMode")
.value("EFirstMode", Example4::EFirstMode)
.value("ESecondMode", Example4::ESecondMode)
.export_values();
}
#!/usr/bin/env python3
import sys
sys.path.append('.')
from example import test_function
from example import some_constant
from example import EMyEnumeration
from example import EFirstEntry
from example import Example4
print(EMyEnumeration)
print(EMyEnumeration.EFirstEntry)
print(EMyEnumeration.ESecondEntry)
print(EFirstEntry)
print(test_function())
print(test_function(7))
print(test_function(EMyEnumeration.EFirstEntry))
print(test_function(EMyEnumeration.ESecondEntry))
print(Example4.EMode)
print(Example4.EMode.EFirstMode)
print(Example4.EFirstMode)
Example4.test_function(Example4.EFirstMode)
test_function()
test_function(7)
test_function(enum=1)
test_function(enum=2)
Example4::test_function(enum=1)
<class 'example.EMyEnumeration'>
EMyEnumeration.EFirstEntry
EMyEnumeration.ESecondEntry
EMyEnumeration.EFirstEntry
False
3.5
None
None
<class 'example.Example4.EMode'>
EMode.EFirstMode
EMode.EFirstMode
/*
example/example5.cpp -- Example 5: inheritance, callbacks, acquiring
and releasing the global interpreter lock
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
*/
#include "example.h"
class Pet {
public:
Pet(const std::string &name, const std::string &species)
: m_name(name), m_species(species) {}
std::string name() const { return m_name; }
std::string species() const { return m_species; }
private:
std::string m_name;
std::string m_species;
};
class Dog : public Pet {
public:
Dog(const std::string &name) : Pet(name, "dog") {}
void bark() const { std::cout << "Woof!" << std::endl; }
};
void pet_print(const Pet &pet) {
std::cout << pet.name() + " is a " + pet.species() << std::endl;
}
void dog_bark(const Dog &dog) {
dog.bark();
}
class Example5 {
public:
Example5(py::handle self, int state)
: self(self), state(state) {
cout << "Constructing Example5.." << endl;
}
~Example5() {
cout << "Destructing Example5.." << endl;
}
void callback(int value) {
py::gil_scoped_acquire gil;
cout << "In Example5::callback() " << endl;
py::object method = self.attr("callback");
method.call(state, value);
}
private:
py::handle self;
int state;
};
bool test_callback1(py::object func) {
func.call();
return false;
}
int test_callback2(py::object func) {
py::object result = func.call("Hello", true, 5);
return result.cast<int>();
}
void test_callback3(Example5 *ex, int value) {
py::gil_scoped_release gil;
ex->callback(value);
}
void init_ex5(py::module &m) {
py::class_<Pet> pet_class(m, "Pet");
pet_class
.def(py::init<std::string, std::string>())
.def("name", &Pet::name)
.def("species", &Pet::species);
py::class_<Dog>(m, "Dog", pet_class)
.def(py::init<std::string>());
m.def("pet_print", pet_print);
m.def("dog_bark", dog_bark);
m.def("test_callback1", &test_callback1);
m.def("test_callback2", &test_callback2);
m.def("test_callback3", &test_callback3);
py::class_<Example5>(m, "Example5")
.def(py::init<py::object, int>());
}
#!/usr/bin/env python3
import sys
sys.path.append('.')
from example import Pet
from example import Dog
from example import dog_bark
from example import pet_print
polly = Pet('Polly', 'parrot')
molly = Dog('Molly')
print(polly.name() + " is a " + polly.species())
pet_print(polly)
print(molly.name() + " is a " + molly.species())
pet_print(molly)
dog_bark(molly)
try:
dog_bark(polly)
except Exception as e:
print('The following error is expected: ' + str(e))
from example import test_callback1
from example import test_callback2
from example import test_callback3
from example import Example5
def func1():
print('Callback function 1 called!')
def func2(a, b, c):
print('Callback function 2 called : ' + str(a) + ", " + str(b) + ", "+ str(c))
return c
class MyCallback(Example5):
def __init__(self, value):
Example5.__init__(self, self, value)
def callback(self, value1, value2):
print('got callback: %i %i' % (value1, value2))
print(test_callback1(func1))
print(test_callback2(func2))
callback = MyCallback(3)
test_callback3(callback, 4)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment