3
0
mirror of https://github.com/triqs/dft_tools synced 2024-12-24 13:23:37 +01:00

Fix compilation of py_converter.

- py_converters in hpp files
- add guard to prevent inclusion in the wrapper (to avoid 2
  specialisation of the same py_converter).
This commit is contained in:
Olivier Parcollet 2014-05-20 17:45:16 +02:00
parent 068c4a116d
commit 8c0bf592d0
16 changed files with 126 additions and 71 deletions

View File

@ -350,6 +350,9 @@ set(TRIQS_LINK_LIBS
# General include header
# remove this dep to C++
include_directories(${TRIQS_SOURCE_DIR})
# for the generated headers for python convertions
include_directories(${CMAKE_BINARY_DIR}/include/)
# Add it to triqs definitions
#--------------------------------
# General C++ compilation flags

View File

@ -6,21 +6,20 @@ include_directories(${PYTHON_INCLUDE_DIRS} ${PYTHON_NUMPY_INCLUDE_DIR})
# ModuleName = the python name of the module
# ModuleDest = path in the pytriqs tree [ FOR INSTALLATION ONLY] IMPROVE MAKE THIS OPTIONAL (for test)
#EXECUTE_PROCESS(COMMAND mkdir -p ${CMAKE_BINARY_DIR}/pytriqs/converters/)
EXECUTE_PROCESS(COMMAND mkdir -p ${CMAKE_BINARY_DIR}/include/pytriqs/converters/)
include_directories( ${CMAKE_BINARY_DIR})
macro (triqs_python_extension ModuleName)
message(STATUS "Preparing extension module ${ModuleName}")
SET(wrap_name ${CMAKE_CURRENT_BINARY_DIR}/${ModuleName}_wrap.cpp)
SET(converter_name ${CMAKE_CURRENT_BINARY_DIR}/${ModuleName}_converter.cpp)
SET(converter_name ${CMAKE_BINARY_DIR}/include/pytriqs/converters/${ModuleName}.hpp)
# Adjust pythonpath so that pytriqs is visible and the wrap_generator too...
# pytriqs needed since we import modules with pure python method to extract the doc..
add_custom_command(OUTPUT ${wrap_name} ${converter_name} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${ModuleName}_desc.py
COMMAND PYTHONPATH=${CMAKE_BINARY_DIR}/pytriqs/wrap_generator:${CMAKE_BINARY_DIR}/ ${PYTHON_INTERPRETER} ${CMAKE_CURRENT_BINARY_DIR}/${ModuleName}_desc.py ${CMAKE_SOURCE_DIR}/pytriqs/wrap_generator/wrapper.mako.cpp ${wrap_name} ${CMAKE_SOURCE_DIR}/pytriqs/wrap_generator/py_converter_wrapper.mako.hpp ${converter_name} )
set_property (GLOBAL APPEND PROPERTY TRIQS_PY_CONVERTERS_CPP_LIST "${CMAKE_CURRENT_BINARY_DIR}/${ModuleName}_converter.cpp")
set_property (GLOBAL APPEND PROPERTY TRIQS_PY_CONVERTERS_TARGETS "python_wrap_${ModuleName}")
add_custom_target(python_wrap_${ModuleName} ALL DEPENDS ${wrap_name} ${converter_name})
@ -33,6 +32,7 @@ macro (triqs_python_extension ModuleName)
target_link_libraries(${ModuleName} ${TRIQS_LINK_LIBS} triqs)
if (${ARGN} MATCHES "")
install (FILES ${converter_name} DESTINATION "include/pytriqs/converters")
install (TARGETS ${ModuleName} DESTINATION ${TRIQS_PYTHON_LIB_DEST}/${ARGN} )
endif (${ARGN} MATCHES "")
#set_property (GLOBAL APPEND PROPERTY DEPENDANCE_TO_ADD triqs_${NickName} )

View File

@ -1,4 +1,4 @@
option(Python_use_mpi4py "Use mpi4py instead of boost.mpi" OFF)
option(Python_use_mpi4py "Use mpi4py (if OFF, use boost.mpi)" OFF)
if (Python_use_mpi4py)
SET (TRIQS_PYTHON_MPI_USE_MPI4PY 1)
else()

View File

@ -2,15 +2,15 @@
SET(PYTHON_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/__init__.py
${CMAKE_CURRENT_SOURCE_DIR}/block_gf.py
${CMAKE_CURRENT_SOURCE_DIR}/descriptor_base.py
${CMAKE_CURRENT_SOURCE_DIR}/descriptors.py
${CMAKE_CURRENT_SOURCE_DIR}/gf_generic.py
${CMAKE_CURRENT_SOURCE_DIR}/gf_imfreq.py
${CMAKE_CURRENT_SOURCE_DIR}/gf_imtime.py
${CMAKE_CURRENT_SOURCE_DIR}/gf_legendre.py
${CMAKE_CURRENT_SOURCE_DIR}/gf_refreq.py
${CMAKE_CURRENT_SOURCE_DIR}/gf_retime.py
${CMAKE_CURRENT_SOURCE_DIR}/gf_two_real_times.py
${CMAKE_CURRENT_SOURCE_DIR}/impl_plot.py
${CMAKE_CURRENT_SOURCE_DIR}/_gf_imfreq.py
${CMAKE_CURRENT_SOURCE_DIR}/_gf_imtime.py
#${CMAKE_CURRENT_SOURCE_DIR}/_gf_legendre.py
${CMAKE_CURRENT_SOURCE_DIR}/_gf_refreq.py
${CMAKE_CURRENT_SOURCE_DIR}/_gf_retime.py
#${CMAKE_CURRENT_SOURCE_DIR}/gf_two_real_times.py
${CMAKE_CURRENT_SOURCE_DIR}/_gf_plot.py
${CMAKE_CURRENT_SOURCE_DIR}/inverse.py
${CMAKE_CURRENT_SOURCE_DIR}/lazy_expressions.py
${CMAKE_CURRENT_SOURCE_DIR}/tools.py

View File

@ -1,7 +1,6 @@
from wrap_generator import *
module = module_(full_name = "pytriqs.gf.local.gf", doc = "Local Green functions ...")
module.add_include("<typeindex>")
module.add_include("<triqs/gfs.hpp>")
module.add_include("<triqs/gfs/local/functions.hpp>")
module.add_include("<triqs/gfs/local/pade.hpp>")
@ -16,6 +15,7 @@ module.add_using("triqs::utility::mini_vector")
t = class_( py_type = "TailGf",
c_type = "local::tail_view",
c_type_absolute = "triqs::gfs::local::tail_view",
serializable= "tuple",
is_printable= True,
arithmetic = ("algebra","double")
@ -85,9 +85,11 @@ module.add_class(t)
########################
module.add_enum(c_name = "statistic_enum",
c_name_absolute = "triqs::gfs::statistic_enum",
values = ["Fermion","Boson"])
module.add_enum(c_name = "mesh_kind",
c_name_absolute = "triqs::gfs::mesh_kind",
values = ["half_bins","full_bins","without_last"])
########################
@ -97,6 +99,7 @@ module.add_enum(c_name = "mesh_kind",
def make_mesh( py_type, c_tag, has_kind=True, is_im=False) :
m = class_( py_type = py_type,
c_type = "gf_mesh<%s>"%c_tag,
c_type_absolute = "triqs::gfs::gf_mesh<triqs::gfs::%s>"%c_tag,
serializable= "tuple",
is_printable= True,
)
@ -196,6 +199,7 @@ def make_gf( py_type, c_tag, is_complex_data = True, is_im = False) :
g = class_(
py_type = py_type,
c_type = "gf_view<%s>"%c_tag,
c_type_absolute = "triqs::gfs::gf_view<triqs::gfs::%s>"%c_tag,
#serializable= "boost",
serializable= "tuple",
is_printable= True,
@ -306,10 +310,6 @@ def make_gf( py_type, c_tag, is_complex_data = True, is_im = False) :
# Pure python methods
g.add_pure_python_method("pytriqs.gf.local._gf_%s.plot"%c_tag, py_name = "_plot_")
g.add_method(py_name = "_as_C_pointer",
calling_pattern = 'auto result = PyCapsule_New(new std::pair<void *,std::type_index>(&self_c,typeid(self_c)),NULL,NULL)',
signature = "PyObject*()")
return g
########################

View File

@ -1,7 +1,7 @@
from wrap_generator import *
# The module
module = module_(full_name = "pytriqs.parameters.parameters.my_module", doc = " Doc of my_module ")
module = module_(full_name = "pytriqs.parameters.parameters", doc = "TO BE WRITTEN")
module.add_include("<triqs/parameters/parameters.hpp>")
module.add_include("<triqs/utility/formatted_output.hpp>")
module.add_using("namespace triqs::params")
@ -9,7 +9,7 @@ module.add_using("namespace triqs::params")
# one class
g = class_(
py_type = "Parameters",
c_type = "parameters",
c_type = "triqs::params::parameters",
#serializable= "tuple",
is_printable= True,
hdf5 = True,

View File

@ -1,5 +1,8 @@
// Specialization of py_converter to types wrapped by the wrap_generator.
// DO NOT EDIT. Generated automatically by wrap_generator
#pragma once
// in case it is included in the module ${module.full_name}.so, we do not want this specialization
#ifndef TRIQS_PYTHON_WRAPPER_MODULE_${module.name}
%for file in module.include_list :
%if file.startswith('<'):
@ -9,39 +12,34 @@
%endif
%endfor
using dcomplex = std::complex<double>;
%for ns in module.using:
using ${ns};
%endfor
//#include <triqs/arrays.hpp>
#include <triqs/python_tools/wrapper_tools.hpp>
namespace triqs { namespace py_tools {
%for n,t in enumerate(module.wrapped_types_by_me) :
%for n,c in enumerate(module.classes.values()) :
template<> void ** py_converter<${t}>::init() {
template<> struct py_converter<${c.c_type_absolute}> {
static void ** init() {
PyObject * mod = PyImport_ImportModule("${module.full_name}");
if (mod ==NULL) return NULL;
void ** table = (void **)PyCapsule_Import("${module.full_name}._exported_wrapper_convert_fnt", 0);
return table;
}
template<> PyObject * py_converter<${t}>::c2py(${t} const & x){
static PyObject * c2py(${c.c_type_absolute} const & x){
static void **wrapped_convert_fnt = init();
if (wrapped_convert_fnt == NULL) return NULL;
return ((PyObject * (*)(${t} const &)) wrapped_convert_fnt[3*${n}])(x);
return ((PyObject * (*)(${c.c_type_absolute} const &)) wrapped_convert_fnt[3*${n}])(x);
}
template<> ${t}& py_converter<${t}>::py2c(PyObject * ob){
static ${c.c_type_absolute}& py2c(PyObject * ob){
static void **wrapped_convert_fnt = init();
if (wrapped_convert_fnt == NULL) std::terminate(); // It should never happen since py2c is called only is is_convertible is true (py_converter specs)
return ((${t}& (*)(PyObject *)) wrapped_convert_fnt[3*${n}+1])(ob);
return ((${c.c_type_absolute}& (*)(PyObject *)) wrapped_convert_fnt[3*${n}+1])(ob);
}
template<> bool py_converter<${t}>::is_convertible(PyObject *ob, bool raise_exception) {
static bool is_convertible(PyObject *ob, bool raise_exception) {
static void **wrapped_convert_fnt = init();
if (wrapped_convert_fnt == NULL) {
if (!raise_exception && PyErr_Occurred()) {PyErr_Print();PyErr_Clear();}
@ -49,6 +47,65 @@ namespace triqs { namespace py_tools {
}
return ((bool (*)(PyObject *,bool)) wrapped_convert_fnt[3*${n}+2])(ob,raise_exception);
}
%endfor
}}
};
%endfor
//--------------------- Converters of regular types --------------------------
%for c in module.classes.values() :
%if c.implement_regular_type_converter :
// ${c.py_type} is wrapping a view, we are also implementing the converter of the associated regular type
template<> struct py_converter<${c.regular_type_absolute}> {
using regular_type = ${c.regular_type_absolute};
using conv = py_converter<${c.c_type_absolute}>;
static PyObject *c2py(regular_type &g) { return conv::c2py(g); }
static PyObject *c2py(regular_type &&g) { return conv::c2py(g); }
static bool is_convertible(PyObject * ob, bool raise_exception) { return conv::is_convertible(ob, raise_exception); }
static regular_type py2c(PyObject *ob) { return conv::py2c(ob); }
};
%endif
%endfor
//--------------------- Converters of enums --------------------------
%for en in module.enums :
namespace triqs { namespace py_tools {
template <> struct py_converter<${en.c_name_absolute}> {
static PyObject * c2py(${en.c_name_absolute} x) {
%for n,val in enumerate(en.values[:-1]) :
if (x == ${val}) return PyString_FromString("${val}");
%endfor
return PyString_FromString("${en.values[-1]}"); // last case separate to avoid no return warning of compiler
}
static ${en.c_name_absolute} py2c(PyObject * ob){
std::string s=PyString_AsString(ob);
%for n,val in enumerate(en.values[:-1]) :
if (s == "${val}") return ${val};
%endfor
return ${en.values[-1]};
}
static bool is_convertible(PyObject *ob, bool raise_exception) {
if (!PyString_Check(ob)) {
if (raise_exception) PyErr_SetString(PyExc_ValueError, "Convertion of C++ enum ${en.c_name_absolute} : the object is not a string");
return false;
}
std::string s=PyString_AsString(ob);
%for n,val in enumerate(en.values) :
if (s == "${val}") return true;
%endfor
if (raise_exception) {
auto err = "Convertion of C++ enum ${en.c_name_absolute} : \nThe string \"" + s +"\" is not in [${','.join([str(x) for x in en.values])}]";
PyErr_SetString(PyExc_ValueError, err.c_str());
}
return false;
}
};
}}
%endfor
}}
#endif

View File

@ -235,6 +235,8 @@ class class_ :
Representation of a wrapped type
Data :
- c_type : C++ type to be wrapped.
- c_type_absolute : full path of c_type, no using, no alias (need for
the py_converter hpp file)
- py_type : Name given in Python
- doc : the doc string.
- c_type_is_view : boolean
@ -244,11 +246,14 @@ class class_ :
- members : a dict : string -> member_
"""
hidden_python_function = {} # global dict of the python function to add to the module, hidden for the user, for precompute and so on
def __init__(self, c_type, py_type, hdf5 = False, arithmetic = None, serializable = None, is_printable = False, doc = '' ) :
def __init__(self, c_type, py_type, c_type_absolute = None, hdf5 = False, arithmetic = None, serializable = None, is_printable = False, doc = '' ) :
self.c_type = c_type
self.c_type_absolute = c_type_absolute or c_type
self.c_type_is_view = is_type_a_view(c_type)
self.implement_regular_type_converter = self.c_type_is_view # by default, it will also make the converter of the associated regular type
if self.c_type_is_view : self.regular_type = 'typename ' + self.c_type + '::regular_type'
if self.c_type_is_view :
self.regular_type = 'typename ' + self.c_type + '::regular_type'
self.regular_type_absolute = 'typename ' + self.c_type_absolute + '::regular_type'
self.py_type = py_type
c_to_py_type[self.c_type] = self.py_type # register the name translation for the doc generation
self.hdf5 = hdf5
@ -420,8 +425,8 @@ class enum_ :
- values : list of string representing the enumerated
- doc : the doc string.
"""
def __init__(self, c_name, values, doc = '') :
self.c_name, self.values, self.doc = c_name, values, doc
def __init__(self, c_name, values, c_name_absolute = None, doc = '') :
self.c_name, self.c_name_absolute, self.values, self.doc = c_name, c_name_absolute or c_name, values, doc
class module_ :
"""
@ -443,7 +448,6 @@ class module_ :
self.classes = {}
self.functions = {}
self.include_list = []
self.wrapped_types_by_me = {}
self.enums = []
self.using =[]
self.python_functions = {}
@ -452,8 +456,8 @@ class module_ :
def add_class(self, cls):
if cls.py_type in self.classes : raise IndexError, "The class %s already exists"%cls.py_type
self.classes[cls.py_type] = cls
self.wrapped_types[cls.c_type] = cls.py_type
self.wrapped_types_by_me[cls.c_type] = cls.py_type
self.wrapped_types[cls.c_type] = cls
self.wrapped_types[cls.c_type_absolute] = cls # we can call is by its name or its absolute name
def add_function(self, **kw):
if "name" in kw :

View File

@ -1,4 +1,5 @@
//--------------------- includes and using -------------------------------------
#define TRIQS_PYTHON_WRAPPER_MODULE_${module.name}
%for file in module.include_list :
%if file.startswith('<'):
@ -966,15 +967,15 @@ init${module.name}(void)
register_h5_reader_for_${c.py_type}();
%endfor
%if len(module.wrapped_types_by_me) >0 :
%if len(module.classes) >0 :
// declare the exported wrapper functions
static void * _exported_wrapped_convert_fnt[3*${len(module.wrapped_types_by_me)}];
static void * _exported_wrapped_convert_fnt[3*${len(module.classes)}];
// init the array with the function pointers
%for n,t in enumerate(module.wrapped_types_by_me) :
_exported_wrapped_convert_fnt[3*${n}] = (void *)convert_to_python<${t}>;
_exported_wrapped_convert_fnt[3*${n}+1] = (void *)convert_from_python<${t}>;
_exported_wrapped_convert_fnt[3*${n}+2] = (void *)convertible_from_python<${t}>;
%for n,c in enumerate(module.classes.values()) :
_exported_wrapped_convert_fnt[3*${n}] = (void *)convert_to_python<${c.c_type_absolute}>;
_exported_wrapped_convert_fnt[3*${n}+1] = (void *)convert_from_python<${c.c_type_absolute}>;
_exported_wrapped_convert_fnt[3*${n}+2] = (void *)convertible_from_python<${c.c_type_absolute}>;
%endfor
/* Create a Capsule containing the API pointer array's address */

View File

@ -1,3 +1,4 @@
#pragma once
#include <iostream>
#include <vector>
#include <ostream>

View File

@ -1,3 +1,4 @@
#pragma once
#include "./a.hpp"
/// some function using A

View File

@ -3,6 +3,7 @@ from wrap_generator import *
# The module
mod = module_(full_name = "pytriqs.wrap_test.my_moduleB", doc = " Doc of my_module ")
mod.add_include("<triqs/../pytriqs/wrap_test/b.hpp>")
mod.add_include("<pytriqs/converters/my_module.hpp>")
mod.add_function (name = "print_a2", signature = "void(A a)", doc = "DOC of print_a")

View File

@ -5,18 +5,6 @@ FOREACH(CPP ${ALLSOURCES})
ENDFOREACH(CPP ${ALLSOURCES})
get_property(ALLSOURCES GLOBAL PROPERTY TRIQS_LIB_CPP_SOURCES_LIST)
## The library also contains all the converters python <-> C++
## automatically generated for all wrapped modules.
## The lists are defined in subdirectory, in each module
## NB : pytriqs subdir is and must be called BEFORE triqs, or these lists are empty
get_property(all_py_converters_sources GLOBAL PROPERTY TRIQS_PY_CONVERTERS_CPP_LIST)
get_property(all_py_converters_targets GLOBAL PROPERTY TRIQS_PY_CONVERTERS_TARGETS)
# All files are generated, cmake should not worry not to see them at configuration time
foreach(CPP ${all_py_converters_sources})
set_source_files_properties(${CPP} PROPERTIES GENERATED TRUE)
endforeach()
# compile every subdirectory
add_all_subdirectories_with_cmakelist()
@ -30,7 +18,8 @@ add_library(triqs ${ALLSOURCES} ${all_py_converters_sources})
target_link_libraries (triqs ${LINK_RT} ${TRIQS_LINK_LIBS} )
# The TRIQS library depends on the generation of the .cpp wrapper and converters files
# which must be produced first.
# which are produced first.
get_property(all_py_converters_targets GLOBAL PROPERTY TRIQS_PY_CONVERTERS_TARGETS)
foreach(T ${all_py_converters_targets})
add_dependencies(triqs ${T})
endforeach()

View File

@ -60,7 +60,7 @@ namespace triqs { namespace mc_tools {
* \param[in] P dictionary parameters
* \param[in] AfterCycleDuty a function bool() to be called after each QMC cycle
*/
mc_generic(utility::parameters const & P, std::function<bool()> AfterCycleDuty = std::function<bool()>() ) :
mc_generic(params::parameters const & P, std::function<bool()> AfterCycleDuty = std::function<bool()>() ) :
RandomGenerator(std::string(P["random_name"]), long(P["random_seed"])),
report(&std::cout,int(P["verbosity"])),
AllMoves(RandomGenerator),

View File

@ -20,6 +20,7 @@
******************************************************************************/
#pragma once
#include "./_field.hpp"
namespace triqs {
namespace params {
@ -100,7 +101,6 @@ namespace params {
p1.update(p2);
return p1;
}
// can only be implemented after complete declaration of parameters
template <typename... T> _field& _field::add_field(T&&... x) {
auto* pp = dynamic_cast<_data_impl<parameters>*>(p.get());
@ -108,7 +108,6 @@ namespace params {
pp->x.add_field(std::forward<T>(x)...);
return *this;
}
}
}
#include <pytriqs/converters/parameters.hpp>

View File

@ -57,12 +57,11 @@ class pyref {
//--------------------- py_converters -----------------------------
// default version for a wrapped type. To be specialized later.
template<typename T> struct py_converter {
static void ** init();
static PyObject * c2py(T const & x);
static T & py2c(PyObject * ob);
static bool is_convertible(PyObject * ob, bool raise_exception);
};
template<typename T> struct py_converter;
//static PyObject * c2py(T const & x);
//static T & py2c(PyObject * ob);
//static bool is_convertible(PyObject * ob, bool raise_exception);
//
// We only use these functions in the code, not converter
// TODO : Does c2py return NULL in failure ? Or is it undefined...