from __future__ import print_function
p = print
import cppyy
cppyy.cppdef("""
struct Integer {
Integer(int i) : num(i) {}
int num;
private:
int p_num = -1;
};
""")
from cppyy.gbl import Integer
m1 = Integer(42)
p(m1.num)
try:
p(m1.p_num)
except:
p('p_num not available')
Integer?
help(Integer)
cppyy.cppdef("""
Integer add(Integer &m1, Integer &m2) {
return Integer(m1.num + m2.num);
}
""")
Integer.__add__ = cppyy.gbl.add # addition from a c++ function
Integer.__repr__ = lambda i : "integer: " + str(i.num) # string representation as python lambda
p(Integer(3) + Integer(39))
cppyy.cppdef("""
struct Base {
virtual std::string method() { return "Base"; }
};
struct Derived : Base {
std::string method() override { return "Derived"; }
};""")
Base, Derived = cppyy.gbl.Base, cppyy.gbl.Derived
p(Base().method())
p(Derived().method())
issubclass(Derived, Base)
cppyy.cppdef("""
struct IntValue {
IntValue(int v) : num(v) {}
IntValue &operator+(const IntValue &i) { num += i.num; return *this; }
IntValue &operator+(int i) { num += i; return *this; }
int num;
};""")
IntValue = cppyy.gbl.IntValue
IntValue.__repr__ = lambda self : str(self.num)
p(IntValue(1) + IntValue(1))
p(IntValue(2**31-1) + IntValue(2**31-1)) # overflow happens in C++, not checked for
try:
(IntValue(2**33))
except:
p("integer overflow")
x, y, z = IntValue(1), IntValue(2), IntValue(3)
p(x + y + z)
vector = cppyy.gbl.vector
v = vector("unsigned short")((0, 8, 42)) # vector[int] and vector("int") also allowed
print(v[0], v[1], v[2])
cppyy.cppdef("""
template <typename T, int N>
struct fac
{
static constexpr int value = N * fac<T, N-1>::value;
};
template <typename T>
struct fac<T, 0>
{
static constexpr int value = 1;
};
""")
from cppyy.gbl import fac
%time print(fac(int, 5).value)
%time print(fac(int, 5).value)
cppyy.cppdef("""
double dub(double x) { return x*2; }
int dub(int x) { return x*2; }
template <typename T>
T dub(T t) { return t + t; }
""")
dub = cppyy.gbl.dub
type(dub(3))
type(dub(3.))
i = IntValue(2)
i2 = dub(i)
print(i2, '---', type(i2))
dub(cppyy.gbl.std.string("coo"))
import cppyy
cppyy.cppdef("""bool isInt(int) { return true; }
bool isInt(double) { return false; }
template <typename ...Args> bool isInt(Args...) { return false; }""")
for i in range(10000):
assert cppyy.gbl.isInt(1) == True
assert cppyy.gbl.isInt(3.) == False
cppyy.cppdef("""
struct Doubler {
int operator()(int t) { return t + t; } // at least one overload must be non-template
template <typename T>
T operator()(T t) { return t + t; }
};
""")
from cppyy.gbl import Doubler
dub = Doubler()
six = dub(IntValue(3))
print(six, '---', type(six))
cppyy.cppdef("""
auto make_lambda() {
int b = 40;
return [&b](int a) { return b+a; };
}
auto l = make_lambda();
""")
print(cppyy.gbl.l(2))
%%file /tmp/cppyy_test.h
std::string bar() { return "oh yeah"; }
cppyy.include('/tmp/cppyy_test.h')
p(cppyy.gbl.bar())
# cppyy.load_library to load the corresponding shared object
cppyy.cppdef("""
int GetNum(IntValue *v) { return v->num; }
""")
cppyy.gbl.GetNum(IntValue(3))
We produce a header, a source file and a linkdef.h
file. The linkdef.h
is a file that lists which classes we want to generate bindings for.
%%file toyproj.h
struct S {
S(int a);
int value;
};
%%file toyproj.cpp
#include "toyproj.h"
S::S(int a) : value(a) {}
%%file linkdef.h
#pragma link C++ class S;
We use rootcling
to produce a file out.cxx
from the header and the linkdef, than compile both out.cxx
and the original source file in a shared library.
%%bash
rootcling -f out.cpp toyproj.h linkdef.h
g++ -fPIC -shared out.cpp toyproj.cpp -o toyproj.so $(cling-config --cppflags)
Finally, we load the shared library into cppyy.
cppyy.load_library('toyproj')
s = cppyy.gbl.S(3)
assert s.value == 3
import cppyy
cppyy.cppdef("""
struct Obj {
int var;
};
template <typename T>
constexpr auto has_var(T t) -> decltype(t.var, true) { return true; }
template <typename ...Args>
constexpr bool has_var(Args...) { return false; }
template <typename T>
constexpr bool call_has_var(T &&t) { return has_var(std::forward<T>(t)); }
void foo() {
static_assert(has_var(Obj()), "");
static_assert(!has_var(3), "");
}
""")
Obj = cppyy.gbl.Obj
#cppyy.gbl.has_var(Obj()) # interpreter crashes
cppyy.gbl.call_has_var(Obj()) # works