Commit 954f0ecd authored by Tadeu Manoel's avatar Tadeu Manoel

Add basic support for std::function

parent 3d4f7a19
cdef extern from "<functional>" namespace "std" nogil:
cdef cppclass function[T]:
function() except +
function(T*) except +
function(function&) except +
function(void*) except +
function operator=(T*)
function operator=(function&)
function operator=(void*)
function operator=[U](U)
bint operator bool()
#include "cpp_function_lib.h"
double add_one(double a, int b)
{
return a + (double) b + 1.0;
}
double add_two(double a, int b)
{
return a + (double) b + 2.0;
}
AddAnotherFunctor::AddAnotherFunctor(double to_add)
: to_add(to_add)
{
}
double AddAnotherFunctor::operator()(double a, int b) const
{
return a + (double) b + this->to_add;
};
FunctionKeeper::FunctionKeeper(std::function<double(double, int)> user_function)
: my_function(user_function)
{
}
FunctionKeeper::~FunctionKeeper()
{
}
void FunctionKeeper::set_function(std::function<double(double, int)> user_function)
{
this->my_function = user_function;
}
std::function<double(double, int)> FunctionKeeper::get_function() const
{
return this->my_function;
}
double FunctionKeeper::call_function(double a, int b) const
{
if (!this->my_function) {
throw std::runtime_error("Trying to call undefined function!");
}
return this->my_function(a, b);
};
#ifndef CPP_FUNCTION_LIB_H
#define CPP_FUNCTION_LIB_H
#include <functional>
// Functions, functor and a holder of std::function used by cpp_stl_function.pyx tests.
double add_one(double a, int b);
double add_two(double a, int b);
class AddAnotherFunctor
{
double to_add;
public:
AddAnotherFunctor(double to_add);
double operator()(double a, int b) const;
};
class FunctionKeeper
{
std::function<double(double, int)> my_function;
public:
FunctionKeeper(std::function<double(double, int)> user_function);
virtual ~FunctionKeeper();
void set_function(std::function<double(double, int)> user_function);
std::function<double(double, int)> get_function() const;
double call_function(double a, int b) const;
};
#endif
from libcpp.functional cimport function
cdef extern from "cpp_function_lib.cpp":
# CPP is include here so that it doesn't need to be compiled externally
pass
cdef extern from "cpp_function_lib.h":
double add_one(double, int)
double add_two(double a, int b)
cdef cppclass AddAnotherFunctor:
AddAnotherFunctor(double to_add)
double call "operator()"(double a, int b)
cdef cppclass FunctionKeeper:
FunctionKeeper(function[double(double, int)] user_function)
void set_function(function[double(double, int)] user_function)
function[double(double, int)] get_function()
double call_function(double a, int b) except +
# distutils: extra_compile_args=-std=c++0x
# mode: run
# tag: cpp
from libcpp.functional cimport function
cimport cpp_function_lib
def test_simple_function():
'''
>>> test_simple_function()
6.0
'''
return cpp_function_lib.add_one(2.0, 3)
def test_AddAnotherFunctor(n):
'''
>>> test_AddAnotherFunctor(5.0)
10.0
'''
return cpp_function_lib.AddAnotherFunctor(5.0).call(2.0, 3)
cdef class FunctionKeeper:
"""
>>> fk = FunctionKeeper('add_one')
>>> fk(2.0, 3)
6.0
>>> fk = FunctionKeeper('add_two')
>>> fk(2.0, 3)
7.0
>>> fk = FunctionKeeper('AddAnotherFunctor5')
>>> fk(2.0, 3)
10.0
>>> fk = FunctionKeeper('default')
>>> bool(fk)
False
>>> fk(2.0, 3)
Traceback (most recent call last):
...
RuntimeError: Trying to call undefined function!
>>> fk.set_function('AddAnotherFunctor5')
>>> fk(2.0, 3)
10.0
>>> bool(fk)
True
>>> fk.set_function('NULL')
>>> bool(fk)
False
"""
cdef cpp_function_lib.FunctionKeeper* function_keeper
cdef function[double(double, int)]* _get_function_ptr_from_name(self, function_name):
cdef function[double(double, int)] *f
if function_name == 'add_one':
f = new function[double(double, int)](cpp_function_lib.add_one)
elif function_name == 'add_two':
f = new function[double(double, int)](cpp_function_lib.add_two)
elif function_name == 'AddAnotherFunctor5':
f = new function[double(double, int)]()
f[0] = cpp_function_lib.AddAnotherFunctor(5.0)
elif function_name == 'NULL':
f = new function[double(double, int)](NULL)
elif function_name == 'default':
f = new function[double(double, int)]()
return f
def __cinit__(self, function_name):
cdef function[double(double, int)] *f = self._get_function_ptr_from_name(function_name)
self.function_keeper = new cpp_function_lib.FunctionKeeper(f[0])
del f
def __dealloc__(self):
del self.function_keeper
def __call__(self, a, b):
return self.function_keeper.call_function(a, b)
def __bool__(self):
return <bint> self.function_keeper.get_function()
def set_function(self, function_name):
cdef function[double(double, int)] *f = self._get_function_ptr_from_name(function_name)
self.function_keeper.set_function(f[0])
del f
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