Commit 3b6d1aa3 authored by gabrieldemarmiesse's avatar gabrieldemarmiesse

Improved the C++ tutorial by running tests on the examples. Moved the section...

Improved the C++ tutorial by running tests on the examples. Moved the section "specifying the language in the setup.py" outside the tutorial to make the tutorial simpler.
parent ad0fb02f
#!/usr/bin/env python
# -*- coding: utf-8 -*-
try:
import rect
except ImportError:
print("Module rect has not yet been built")
print("Please run $python setup.py build_ext --inplace")
print("Then try again")
import sys
sys.exit()
x0, y0, x1, y1 = 1, 2, 3, 4
rect_obj = rect.PyRectangle(x0, y0, x1, y1)
print(dir(rect_obj))
from distutils.core import setup, Extension
from Cython.Build import cythonize
setup(ext_modules = cythonize("rect.pyx"))
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import unittest
import os
class TestRectangleCppExtension(unittest.TestCase):
def setUp(self):
self.directory_at_runtime = os.listdir()
os.system("python setup.py build_ext --inplace")
import rect
self.x0, self.y0, self.x1, self.y1 = 1, 2, 3, 4
self.rect_obj = rect.PyRectangle(self.x0, self.y0, self.x1, self.y1)
def test_get_area(self):
width = self.x1 - self.x0
height = self.y1 - self.y0
area = width * height
self.assertEqual(
self.rect_obj.get_area(),
area)
def test_get_size(self):
true_width = self.x1 - self.x0
true_height = self.y1 - self.y0
width, height = self.rect_obj.get_size()
self.assertEqual(true_width, width)
self.assertEqual(true_height, height)
def test_move(self):
x0, x1 = self.rect_obj.x0, self.rect_obj.x1
y0, y1 = self.rect_obj.y0, self.rect_obj.y1
dx, dy = 10, 5
self.rect_obj.move(dx, dy)
self.assertEqual(
(x0+dx, x1+dx, y0+dy, y1+dy),
(self.rect_obj.x0, self.rect_obj.x1,
self.rect_obj.y0, self.rect_obj.y1))
def tearDown(self):
files_to_remove = [f for f in os.listdir()
if f not in self.directory_at_runtime]
for f in files_to_remove:
if os.path.isfile(f):
os.remove(f)
elif os.path.isdir(f):
os.system("rm -rf {}".format(f))
if __name__ == "__main__":
unittest.main()
cdef extern from "Rectangle.cpp":
pass
# Decalre 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
def main():
rec_ptr = new Rectangle(1, 2, 3, 4) # Instantiate a Rectangle object on the heap
try:
rec_area = rec_ptr.getArea()
finally:
del rec_ptr # delete heap allocated object
cdef Rectangle rec_stack # Instantiate a Rectangle object on the stack
import rect
x0, y0, x1, y1 = 1, 2, 3, 4
rect_obj = rect.PyRectangle(x0, y0, x1, y1)
print(dir(rect_obj))
# distutils: language = c++
from Rectangle cimport Rectangle
# Create a Cython extension type which holds a C++ instance
# as an attribute and create a bunch of forwarding methods
# Python extension type.
cdef class PyRectangle:
cdef Rectangle c_rect # Hold a C++ instance which we're wrapping
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)
# distutils: language = c++
from Rectangle cimport Rectangle
cdef class PyRectangle:
cdef Rectangle*c_rect # hold a pointer to the C++ instance which we're wrapping
def __cinit__(self, int x0, int y0, int x1, int y1):
self.c_rect = new Rectangle(x0, y0, x1, y1)
def __dealloc__(self):
del self.c_rect
# distutils: language = c++
# distutils: sources = Rectangle.cpp
# Decalre 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)
from Rectangle cimport Rectangle
# Create a Cython extension type which holds a C++ instance
# as an attribute and create a bunch of forwarding methods
# Python extension type:
cdef class PyRectangle:
cdef Rectangle c_rect
cdef Rectangle c_rect # Hold a C++ instance which we're wrapping
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)
......@@ -48,7 +35,6 @@ cdef class PyRectangle:
def x1(self, x1):
self.c_rect.x1 = x1
# Attribute access
@property
def y0(self):
......@@ -64,17 +50,3 @@ cdef class PyRectangle:
@y1.setter
def y1(self, y1):
self.c_rect.y1 = y1
def main():
rec_ptr = new Rectangle(1, 2, 3, 4) # Instantiate a Rectangle object on the heap
try:
recArea = rec_ptr.getArea()
finally:
del rec_ptr # delete heap allocated object
cdef Rectangle rec_stack # Instantiate a Rectangle object on the stack
if __name__ == "__main__":
main()
from distutils.core import setup
from Cython.Build import cythonize
setup(ext_modules=cythonize("rect.pyx"))
This diff is collapsed.
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