from IPython.core.display import HTML
HTML("<style>.container { width:100% !important; }</style>")
Caso: Función sencilla sin argumentos y ningún valor de retorno
WrapperFunciones/src/hola_mundo/ejemplo1.cpp
#include <iostream>
#include <string>
#include <boost/python.hpp>
void HolaMundo() {
std::cout << "Hola Mundo" << std::endl;
}
BOOST_PYTHON_MODULE(ejemplo1)
{
boost::python::def("hola_mundo", HolaMundo,"Funcion que muestra nuestro primer saludo");
}
Código para compilar:
g++ -I/usr/include/python3.4m -c -std=c++14 -fPIC -o ejemplo1.o ejemplo1.cpp
g++ -shared -lboost_python3 -o "ejemplo1.so" ./ejemplo1.o
Caso: Tenemos una función que multiplica un factor a cada elemento del vector:
WrapperFunciones/src/vector/multiplicacion.cpp
#include <vector>
#include <algorithm>
#include "multiplicacion.h"
std::vector<double> Multiplicacion(const std::vector<double> &datos, double factor) {
std::vector<double> datos_transformados(datos);
std::transform(datos_transformados.begin(), datos_transformados.end(),
datos_transformados.begin(),
[&factor](auto a) {return (a*factor);});
return datos_transformados;
}
WrapperFunciones/src/vector/ejemplo7.cpp
#include <iostream>
#include <boost/python.hpp>
#include "boost/python/stl_iterator.hpp"
#include "boost/python/numeric.hpp"
#include <boost/assign/std/vector.hpp>
#include "multiplicacion.h"
namespace py = boost::python;
py::numeric::array wrapper_multiplicacion(const py::numeric::array& datos, double factor = 1) {
// numpy -> std::vector
py::stl_input_iterator<double> begin(datos), end;
std::vector<double> datos_transformar(begin, end);
// LLamada a la función
auto nuevos_datos = Multiplicacion(datos_transformar, factor);
// std::vector -> numpy
py::list resultado;
for (auto const &i : nuevos_datos)
resultado.append(i);
return py::numeric::array(resultado);
}
BOOST_PYTHON_FUNCTION_OVERLOADS(args_por_defecto_multiplicacion, wrapper_multiplicacion, 1, 2);
BOOST_PYTHON_MODULE(ejemplo7)
{
py::numeric::array::set_module_and_type("numpy", "ndarray");
py::def("wrapper_multiplicacion", wrapper_multiplicacion,args_por_defecto_multiplicacion());
}
import numpy as np
factor_multiplicacion=1.5
numero_de_elementos=5
vector = np.arange(numero_de_elementos,dtype=np.float64)
vector
array([ 0., 1., 2., 3., 4.])
import ejemplo7
ejemplo7.wrapper_multiplicacion(vector,factor_multiplicacion)
array([ 0. , 1.5, 3. , 4.5, 6. ])
C++ | Python | Notas |
---|---|---|
std::vector< double > | numpy | En realidad cualquier clase iterable que se pueda construir por medio de iteradores y que la clase que contenga, tenga definido el constructor copia |
boost::posix_time::time_duration | datetime.timedelta | |
boost::gregorian::date | datetime.date | |
boost::posix_time::ptime | datetime | |
boost::local_time::local_date_time | datetime | Por ahora, únicamente reconoce la zona horaria UTC |
Ejemplos: std::vector a numpy y viceversa
WrapperFunciones/src/vector/ejemplo8.cpp
#include <iostream>
#include <boost/python.hpp>
#include "multiplicacion.h"
#include "../../../WrapperClases/convertidores/include/envoltorio_objetos_iterables.h" // Donde está definido el conversor
namespace py = boost::python;
BOOST_PYTHON_FUNCTION_OVERLOADS(args_por_defecto_multiplicacion, multiplicacion, 1, 2);
BOOST_PYTHON_MODULE(ejemplo8){
convertidores::RegistrarObjetosIterables<std::vector<double>>(); // Se registra
py::def("wrapper_multiplicacion", Multiplicacion);
}
import ejemplo8
ejemplo8.wrapper_multiplicacion(vector,factor_multiplicacion)
array([ 0. , 1.5, 3. , 4.5, 6. ])
Caso1 : Vamos a extender la clase Serie de una librerÃa externa
WrapperClases/utiles/include/Serie.h
class Serie: private std::vector<double> {
typedef std::vector<double> vector;
public:
Serie();
Serie(const std::vector<double> &serie, const boost::posix_time::ptime &fecha_inicio,
const boost::posix_time::time_duration &resolucion = boost::posix_time::seconds(3600),
std::string descripcion = "");
boost::posix_time::ptime UltimaFechaValida() const;
boost::posix_time::ptime PrimeraFecha() const;
Serie Copiar() const;
const std::vector<double>& GetValores() const;
std::string GetDescripcion() const;
void SetDescripcion(std::string descripcion);
boost::posix_time::time_duration GetResolucion() const;
bool operator==(Serie const& otra_serie) const;
using vector::operator[];
using vector::begin;
using vector::end;
using vector::size;
using vector::iterator;
private:
boost::posix_time::ptime fecha_inicio;
boost::posix_time::time_duration resolucion;
std::string descripcion;
};
Serie operator+(const Serie& serie, double valor);
Serie operator-(const Serie& serie, double valor);
std::ostream &operator<<(std::ostream &os, const Serie &serie);
WrapperClases/wrapper_utiles/wrapper_utiles/src/serie.cpp
py::class_<utiles::Serie>("Serie",
py::init<std::vector<double>,boost::posix_time::ptime const&,py::optional<boost::posix_time::time_duration,std::string>>
(( py::arg("datos"),
py::arg("fecha_inicio"),
py::arg("resolucion")="3600",
py::arg("descripcion")=""
), "Constructor de la serie") )
.def("ultima_fecha_valida",&utiles::Serie::UltimaFechaValida) // boost::posix_time::ptime UltimaFechaValida() const;
.def("primera_fecha",&utiles::Serie::PrimeraFecha) // boost::posix_time::ptime PrimeraFecha() const;
.def_readonly("resolucion",&utiles::Serie::GetResolucion) // boost::posix_time::time_duration GetResolucion() const;
.add_property("descripcion",&utiles::Serie::GetDescripcion,&utiles::Serie::SetDescripcion) // std::string GetDescripcion() const, void SetDescripcion(std::string descripcion);
.def("valores", &utiles::Serie::GetValores,py::return_value_policy<py::copy_const_reference>()) //const std::vector<double> &GetValores() const;
.def(str(py::self)) // std::ostream &operator<<(std::ostream &os, const Serie &serie);
.def(repr(py::self)) // std::ostream &operator<<(std::ostream &os, const Serie &serie);
.def(py::self + double()) // Serie operator+(const Serie& serie, double valor);
.def(py::self - double()) // Serie operator-(const Serie& serie, double valor);
.def("__eq__",&utiles::Serie::operator==) // bool operator==(Serie const& otra_serie) const;
.def("__iter__",py::iterator<utiles::Serie>()) // using vector::iterator;
.def("__getitem__",&GetItemSerie) // using vector::operator[];
.def("__getitem__",&GetItemSliceSerie); // using vector::begin; using vector::end;
double GetItemSerie(const utiles::Serie& self, int index) {
if (index < 0)
index += static_cast<int>(self.size());
if (index < 0 || static_cast<int>(self.size()) <= index)
throw std::out_of_range("Fuera de rango");
return self[index];
}
py::numeric::array GetItemSliceSerie(const utiles::Serie& self,
py::slice slice) {
py::list resultado;
py::slice::range<std::vector<double>::const_iterator> rango;
try {
rango = slice.get_indices(self.begin(), self.end());
} catch (std::invalid_argument&) {
return py::numeric::array(resultado);
}
for (; rango.start != rango.stop; std::advance(rango.start, rango.step)) {
resultado.append(*rango.start);
}
resultado.append(*rango.start); //Ultimo elemento
return py::numeric::array(resultado);
}
Leeremos y jugaremos con los datos de observación de demanda y temperatura de de un estado de new york
import datetime as dt
import pandas as pd
import numpy as np
import sys
from bokeh.plotting import Figure,output_notebook,show
from bokeh.models import ColumnDataSource,HoverTool
output_notebook()