# mode: run
# tag: cpp, werror
# cython: experimental_cpp_class_def=True
# distutils: extra_compile_args=-std=c++0x
cdef double pi
from math import pi
from libc.math cimport sin, cos
from libcpp cimport bool
from libcpp.memory cimport unique_ptr
from libcpp.vector cimport vector
from cython.operator cimport dereference as deref
cdef extern from "shapes.h" namespace "shapes":
cdef cppclass Shape:
float area() const
cdef cppclass RegularPolygon(Shape):
float radius # major
int n
__init__(int n, float radius):
this.n = n
this.radius = radius
float area() const:
cdef double theta = pi / this.n
return this.radius * this.radius * sin(theta) * cos(theta) * this.n
def test_Poly(int n, float radius=1):
"""
>>> test_Poly(4)
2.0
>>> test_Poly(3) #doctest: +ELLIPSIS
1.29903...
>>> test_Poly(3, 10.0) #doctest: +ELLIPSIS
129.903...
>>> test_Poly(100) #doctest: +ELLIPSIS
3.13952...
>>> test_Poly(1000) #doctest: +ELLIPSIS
3.14157...
"""
cdef RegularPolygon* poly
try:
poly = new RegularPolygon(n, radius)
poly.n = n
poly.radius = radius
return poly.area()
finally:
del poly
cdef cppclass BaseClass:
int n
int method():
return this.n
cdef cppclass SubClass(BaseClass):
bool override
__init__(bool override):
this.n = 1
this.override = override
int method():
if override:
return 0
else:
return BaseClass.method()
def test_BaseMethods(x):
"""
>>> test_BaseMethods(True)
0
>>> test_BaseMethods(False)
1
"""
cdef SubClass* subClass
try:
subClass = new SubClass(x)
return subClass.method()
finally:
del subClass
cdef cppclass WithStatic:
@staticmethod
double square(double x):
return x * x
def test_Static(x):
"""
>>> test_Static(2)
4.0
>>> test_Static(0.5)
0.25
"""
return WithStatic.square(x)
cdef cppclass InitDealloc:
__init__():
try:
print "Init"
finally:
return # swallow any exceptions
__dealloc__():
try:
print "Dealloc"
finally:
return # swallow any exceptions
def test_init_dealloc():
"""
>>> test_init_dealloc()
start
Init
live
Dealloc
end
"""
print "start"
cdef InitDealloc *ptr = new InitDealloc()
print "live"
del ptr
print "end"
cdef cppclass WithTemplate[T]:
T value
void set_value(T value):
this.value = value
T get_value():
return this.value
cdef cppclass ResolveTemplate(WithTemplate[long]):
pass
def test_templates(long value):
"""
>>> test_templates(10)
>>> test_templates(-2)
"""
cdef WithTemplate[long] *base = new WithTemplate[long]()
del base
cdef ResolveTemplate *resolved = new ResolveTemplate()
resolved.set_value(value)
assert resolved.value == resolved.get_value() == value, resolved.value
base = resolved
base.set_value(2 * value)
assert base.get_value() == base.value == 2 * value, base.value
del base
cdef cppclass Simple:
pass
def test_default_init_no_gil():
with nogil:
s = new Simple()
del s
cdef class NoisyAlloc(object):
cdef public name
def __init__(self, name):
print "NoisyAlloc.__init__", name
self.name = name
def __dealloc__(self):
try:
print "NoisyAlloc.__dealloc__", self.name
except:
pass # Suppress unraisable exception warning.
def __repr__(self):
return "NoisyAlloc[%s]" % self.name
cdef cppclass CppClassWithObjectMember:
NoisyAlloc o
__init__(name):
try:
print "CppClassWithObjectMember.__init__", name
this.o = NoisyAlloc(name)
except:
pass # Suppress unraisable exception warning.
__dealloc__():
try:
print "CppClassWithObjectMember.__dealloc__", this.o.name
except:
pass # Suppress unraisable exception warning.
def test_CppClassWithObjectMember(name):
"""
>>> test_CppClassWithObjectMember("gertrude")
CppClassWithObjectMember.__init__ gertrude
NoisyAlloc.__init__ gertrude
CppClassWithObjectMember.__dealloc__ gertrude
NoisyAlloc.__dealloc__ gertrude
"""
x = new CppClassWithObjectMember(name)
del x
def test_CppClassWithObjectMemberCopyAssign(name):
"""
>>> test_CppClassWithObjectMemberCopyAssign("gretel")
CppClassWithObjectMember.__init__ gretel
NoisyAlloc.__init__ gretel
CppClassWithObjectMember.__dealloc__ gretel
Alive in vector NoisyAlloc[gretel]
CppClassWithObjectMember.__init__ leterg
NoisyAlloc.__init__ leterg
NoisyAlloc.__dealloc__ gretel
CppClassWithObjectMember.__dealloc__ leterg
Alive in vector NoisyAlloc[leterg]
CppClassWithObjectMember.__dealloc__ leterg
NoisyAlloc.__dealloc__ leterg
Nothing alive.
"""
x = new CppClassWithObjectMember(name)
cdef vector[CppClassWithObjectMember] v
# Invokes copy constructor.
v.push_back(deref(x))
del x
print "Alive in vector", v[0].o
y = new CppClassWithObjectMember(name[::-1])
# Invokes copy assignment.
v[0] = deref(y)
del y
print "Alive in vector", v[0].o
v.clear()
print "Nothing alive."
# Github issue #1886.
cdef public cppclass PublicCppClassWithObjectMember:
object o
def test_PublicCppClassWithObjectMember():
"""
>>> test_PublicCppClassWithObjectMember()
"""
cdef PublicCppClassWithObjectMember c
assert c.o is None
cdef cppclass UncopyableConstructorArgument:
unique_ptr[vector[int]] member
__init__(unique_ptr[vector[int]] arg):
this.member.reset(arg.release())
def test_uncopyable_constructor_argument():
"""
>>> test_uncopyable_constructor_argument()
"""
cdef UncopyableConstructorArgument *c = new UncopyableConstructorArgument(
unique_ptr[vector[int]](new vector[int]()))
del c