switch to cpp wrapper -> first array wrapper works

This commit is contained in:
Christian Zimmermann 2023-05-24 00:41:11 +02:00
parent 4d2e9fc6e7
commit c0fb3fe7ea
11 changed files with 105 additions and 464 deletions

1
.gitignore vendored
View file

@ -2,4 +2,3 @@
build/ build/
cnorxz.egg-info/ cnorxz.egg-info/
*.so *.so
*.cpp

View file

@ -1,60 +0,0 @@
from libcpp.memory cimport shared_ptr
from range cimport cpp_RangeBase
from index cimport cpp_YIndex
cdef extern from "array/array.h" namespace "CNORXZ":
cdef cppclass cpp_AIndex "CNORXZ::AIndex" [T] (cpp_YIndex):
cpp_AIndex() except+
cpp_AIndex(const cpp_AIndex&) except+
cpp_AIndex(const T*, const shared_ptr[cpp_RangeBase]&, size_t lexpos) except+
cpp_AIndex(const T*, const cpp_YIndex&) except+
cpp_AIndex A_plus "operator+" (int n) except+
cpp_AIndex A_minus "operator-" (int n) except+
const T& A_get "operator*" () except+
cdef extern from "array/array.h" namespace "CNORXZ":
cdef cppclass cpp_BIndex "CNORXZ::BIndex" [T] (cpp_AIndex[T]):
cpp_BIndex() except+
cpp_BIndex(const cpp_AIndex[T]&) except+
cpp_BIndex(const T*, const shared_ptr[cpp_RangeBase]&, size_t lexpos) except+
cpp_BIndex(const T*, const cpp_AIndex[T]&) except+
cpp_BIndex B_plus "operator+" (int n) except+
cpp_BIndex B_minus "operator-" (int n) except+
T& B_get "operator*" () except+
cdef extern from "array/array.h" namespace "CNORXZ":
cdef cppclass cpp_CArrayBase "CNORXZ::CArrayBase" [T]:
cpp_CArrayBase() except+
cpp_CArrayBase(const cpp_CArrayBase[T]&) except+
size_t size() except+
shared_ptr[cpp_RangeBase] range() except+
cpp_AIndex[T] begin() except+
cpp_AIndex[T] end() except+
cdef extern from "array/array.h" namespace "CNORXZ":
cdef cppclass cpp_ArrayBase "CNORXZ::ArrayBase" [T] (cpp_CArrayBase[T]):
cpp_ArrayBase() except+
cpp_ArrayBase(const cpp_ArrayBase[T]&) except+
cpp_BIndex[T] begin() except+
cpp_BIndex[T] end() except+
cdef extern from "array/array.h" namespace "CNORXZ":
cdef cppclass cpp_MArray "CNORXZ::MArray" [T] (cpp_ArrayBase[T]):
cpp_MArray() except+
cpp_MArray(const cpp_MArray[T]&) except+
cpp_MArray(const shared_ptr[cpp_RangeBase]&) except+

View file

@ -1,24 +0,0 @@
from libcpp.string cimport string
from array cimport cpp_MArray
cdef extern from "cereal/cnorxz_cereal.h" namespace "CNORXZ::cer":
cdef cppclass cpp_Format "CNORXZ::cer::Format":
pass
cdef extern from "cereal/cnorxz_cereal.h" namespace "CNORXZ::cer::Format":
cdef cpp_Format BINARY
cdef cpp_Format JSON
cdef cpp_Format XML
cdef extern from "cereal/cnorxz_cereal.h" namespace "CNORXZ::cer":
cdef void cpp_writeJSONFile "CNORXZ::cer::writeJSONFile" [T] (const string&, const cpp_MArray[T]&)
cdef extern from "cereal/cnorxz_cereal.h" namespace "CNORXZ::cer":
cdef void cpp_writeBINARYFile "CNORXZ::cer::writeBINARYFile" [T] (const string&, const cpp_MArray[T]&)
cdef extern from "cereal/cnorxz_cereal.h" namespace "CNORXZ::cer":
cdef void cpp_readJSONFile "CNORXZ::cer::readJSONFile" [T] (const string&, cpp_MArray[T]&)
cdef extern from "cereal/cnorxz_cereal.h" namespace "CNORXZ::cer":
cdef void cpp_readBINARYFile "CNORXZ::cer::readBINARYFile" [T] (const string&, cpp_MArray[T]&)

34
cnorxz/core/core.cpp Normal file
View file

@ -0,0 +1,34 @@
#include <Python.h>
#include "array_wrapper.h"
using namespace CNORXZ;
static PyModuleDef cnorxz_core_module = {
PyModuleDef_HEAD_INIT,
"cnorxz",
"cnorxz core module",
-1,
NULL, NULL, NULL, NULL, NULL
};
PyMODINIT_FUNC PyInit_cnorxz()
{
PyObject* m;
PyTypeObject* carray_type = PyCArrayBType_init();
if(carray_type == NULL){
return NULL;
}
m = PyModule_Create(&cnorxz_core_module);
if(m == NULL){
return NULL;
}
Py_INCREF(carray_type);
PyModule_AddObject(m, "CArray", (PyObject*) carray_type);
return m;
}

View file

@ -1,284 +0,0 @@
#cython: language_level=3
#cython: c_string_type=str
#cython: c_string_encoding=ascii
#cython: boundscheck=False
#cython: wrapparound=False
#cython: cdivision=True
#cython: embedsignature=True
from libcpp.memory cimport shared_ptr, make_shared, dynamic_pointer_cast
from libcpp.string cimport string
from libcpp cimport bool
from cython.operator cimport dereference as deref
from range cimport cpp_RangeBase
from range_factory cimport cpp_RangeFactoryBase, cpp_CRangeFactory
from array cimport cpp_CArrayBase, cpp_MArray, cpp_AIndex
from index cimport cpp_DIndex
from cereal cimport cpp_writeJSONFile, cpp_writeBINARYFile, cpp_readJSONFile, cpp_readBINARYFile
## ============
## Range
## ============
cdef class Range:
cdef shared_ptr[cpp_RangeBase] cpp_range
def size(self):
return self.cpp_range.get().size()
def dim(self):
return self.cpp_range.get().dim()
def sub(self):
return getSubRange(self)
def index(self):
return getRangeIndex(self)
cdef class RangeFactory:
cdef shared_ptr[cpp_RangeFactoryBase] cpp_rfactory
def __cinit__(self,rangetype,**kvargs):
cdef size_t size = 0
if rangetype == 'C':
size = kvargs['size']
self.cpp_rfactory = dynamic_pointer_cast[cpp_RangeFactoryBase,cpp_CRangeFactory](
make_shared[cpp_CRangeFactory](size))
else:
raise Exception('unknown range type:'+ rangetype)
def create(self):
r = Range()
r.cpp_range = self.cpp_rfactory.get().create()
return r
## ===========
## Index
## ===========
cdef class Index:
def __iter__(self):
return self
def __next__(self):
return self
def lex(self):
return 0
def dim(self):
return 0
def stringMeta(self):
return ''
cdef class DIndex (Index):
cdef shared_ptr[cpp_DIndex] cpp_index
cdef bool itercall
def __cinit__(self,_range,_lexpos=0):
cdef Range r = _range
cdef size_t l = _lexpos
self.cpp_index = make_shared[cpp_DIndex] (r.cpp_range,l)
self.itercall = False
def __iter__(self):
self.cpp_index.get().setlpos(0)
self.itercall = True # otherwise first (i.e. zeroth) will be excluded
return self
def __next__(self):
cdef DIndex ret = self
if self.itercall:
ret.itercall = False
return ret
if self.lex() < self.cpp_index.get().range().get().size()-1:
ret.cpp_index = make_shared[cpp_DIndex] (self.cpp_index.get().plus(1))
return ret
else:
raise StopIteration
def lex(self):
return self.cpp_index.get().lex()
def dim(self):
return self.cpp_index.get().dim()
def stringMeta(self):
return self.cpp_index.get().stringMeta()
def getRangeIndex(_range):
return DIndex(_range)
## ===========
## Array
## ===========
cdef class Array:
def size(self):
return 0
def range(self):
cdef Range r = Range()
return r
cdef class Array_Double (Array):
cdef shared_ptr[cpp_CArrayBase[double]] cpp_array
def __cinit__(self,_range=None):
cdef Range r
if not _range is None:
r = _range
self.cpp_array = dynamic_pointer_cast[cpp_CArrayBase[double],cpp_MArray[double]] (make_shared[cpp_MArray[double]] (r.cpp_range) )
def size(self):
return self.cpp_array.get().size()
def range(self):
cdef Range r = Range()
r.cpp_range = self.cpp_array.get().range()
return r
def index(self):
return AIndex_Double(self)
cdef class Array_Range (Array):
cdef shared_ptr[cpp_CArrayBase[shared_ptr[cpp_RangeBase]]] cpp_array
def __cinit__(self,_range=None):
cdef Range r
if not _range is None:
r = _range
self.cpp_array = dynamic_pointer_cast[cpp_CArrayBase[shared_ptr[cpp_RangeBase]],cpp_MArray[shared_ptr[cpp_RangeBase]]] (make_shared[cpp_MArray[shared_ptr[cpp_RangeBase]]] (r.cpp_range) )
def size(self):
return self.cpp_array.get().size()
def range(self):
cdef Range r = Range()
r.cpp_range = self.cpp_array.get().range()
return r
def index(self):
return AIndex_Range(self)
def getSubRange(_range):
cdef Range r = _range
cdef Array_Range a = Array_Range()
a.cpp_array = dynamic_pointer_cast[cpp_CArrayBase[shared_ptr[cpp_RangeBase]],cpp_MArray[shared_ptr[cpp_RangeBase]]] (make_shared[cpp_MArray[shared_ptr[cpp_RangeBase]]] (r.cpp_range.get().sub()) )
return a
def writeFile(_fname,_array,_format):
cdef Array_Double a = _array
cdef shared_ptr[cpp_MArray[double]] ap = dynamic_pointer_cast[cpp_MArray[double],cpp_CArrayBase[double]](a.cpp_array)
if _format.upper() == "JSON":
cpp_writeJSONFile[double](_fname, deref(ap.get()))
elif _format.upper() == "BINARY":
cpp_writeBINARYFile[double](_fname, deref(ap.get()))
else:
raise Exception("unknown array file format '{}'".format(_format))
def readFile(_fname,_format):
cdef Array_Double a = Array_Double()
cdef shared_ptr[cpp_MArray[double]] ap = make_shared[cpp_MArray[double]]()
a.cpp_array = dynamic_pointer_cast[cpp_CArrayBase[double],cpp_MArray[double]](ap)
if _format.upper() == "JSON":
cpp_readJSONFile[double](_fname, deref(ap.get()))
elif _format.upper() == "BINARY":
cpp_readBINARYFile[double](_fname, deref(ap.get()))
else:
raise Exception("unknown array file format '{}'".format(_format))
return a
cdef class AIndex_Double (Index):
cdef shared_ptr[cpp_CArrayBase[double]] cpp_array # keep the instance alive
cdef shared_ptr[cpp_AIndex[double]] cpp_index
cdef bool itercall
def __cinit__(self,_array,_lexpos=0):
cdef size_t l = _lexpos
cdef Array_Double a = _array
self.cpp_array = a.cpp_array
self.cpp_index = make_shared[cpp_AIndex[double]] (a.cpp_array.get().begin().A_plus(l))
self.itercall = False
def __iter__(self):
self.cpp_index.get().setlpos(0)
self.itercall = True # otherwise first (i.e. zeroth) will be excluded
return self
def __next__(self):
cdef AIndex_Double ret = self
if self.itercall:
ret.itercall = False
return ret
if self.lex() < self.cpp_index.get().range().get().size()-1:
ret.cpp_index = make_shared[cpp_AIndex[double]] (self.cpp_index.get().A_plus(1))
return ret
else:
raise StopIteration
def lex(self):
return self.cpp_index.get().lex()
def dim(self):
return self.cpp_index.get().dim()
def stringMeta(self):
return self.cpp_index.get().stringMeta()
def get(self):
return self.cpp_index.get().A_get()
cdef class AIndex_Range (Index):
cdef shared_ptr[cpp_CArrayBase[shared_ptr[cpp_RangeBase]]] cpp_array # keep the instance alive
cdef shared_ptr[cpp_AIndex[shared_ptr[cpp_RangeBase]]] cpp_index
cdef bool itercall
def __cinit__(self,_array,_lexpos=0):
cdef size_t l = _lexpos
cdef Array_Range a = _array
self.cpp_array = a.cpp_array
self.cpp_index = make_shared[cpp_AIndex[shared_ptr[cpp_RangeBase]]] (a.cpp_array.get().begin().A_plus(l))
self.itercall = False
def __iter__(self):
self.cpp_index.get().setlpos(0)
self.itercall = True # otherwise first (i.e. zeroth) will be excluded
return self
def __next__(self):
cdef AIndex_Range ret = self
if self.itercall:
ret.itercall = False
return ret
if self.lex() < self.cpp_index.get().range().get().size()-1:
ret.cpp_index = make_shared[cpp_AIndex[shared_ptr[cpp_RangeBase]]] (self.cpp_index.get().A_plus(1))
return ret
else:
raise StopIteration
def lex(self):
return self.cpp_index.get().lex()
def dim(self):
return self.cpp_index.get().dim()
def stringMeta(self):
return self.cpp_index.get().stringMeta()
def get(self):
cdef Range r = Range()
r.cpp_range = self.cpp_index.get().A_get()
return r

View file

@ -1,4 +1,7 @@
#ifndef __python_cnorxz_array_wrapper_h__
#define __python_cnorxz_array_wrapper_h__
#include <Python.h> #include <Python.h>
#include "cnorxz.h" #include "cnorxz.h"
@ -8,7 +11,7 @@ namespace CNORXZ
class CArrayWrapperBase class CArrayWrapperBase
{ {
public: public:
DEFAULT_MEMBERS(ArrayWrapperBase); DEFAULT_MEMBERS(CArrayWrapperBase);
virtual ~CArrayWrapperBase() = default; virtual ~CArrayWrapperBase() = default;
virtual RangePtr range() const = 0; virtual RangePtr range() const = 0;
@ -23,7 +26,8 @@ namespace CNORXZ
Sptr<CArrayBase<T>> mArr; Sptr<CArrayBase<T>> mArr;
public: public:
DEFAULT_MEMBERS(ArrayWrapper); CArrayWrapper() : mArr( std::make_shared<MArray<T>>() ) {}
//DEFAULT_MEMBERS(CArrayWrapper);
CArrayWrapper(const RangePtr& r) : mArr( std::make_shared<MArray<T>>(r) ) {} CArrayWrapper(const RangePtr& r) : mArr( std::make_shared<MArray<T>>(r) ) {}
virtual RangePtr range() const override final { return mArr->range(); } virtual RangePtr range() const override final { return mArr->range(); }
@ -37,3 +41,13 @@ struct PyCArrayB
PyObject_HEAD PyObject_HEAD
CNORXZ::CArrayWrapperBase* ptrObj; CNORXZ::CArrayWrapperBase* ptrObj;
}; };
int PyCArrayB_init(PyCArrayB* self, PyObject* args, PyObject* kwds);
void PyCArrayB_dealloc(PyCArrayB* self);
PyObject* PyCArrayB_size(PyCArrayB* self);
PyTypeObject* PyCArrayBType_init();
extern PyMethodDef PyCArrayB_methods[];
extern PyTypeObject PyCArrayBType;
#endif

View file

@ -1,44 +0,0 @@
from libcpp.memory cimport shared_ptr
from libcpp.string cimport string
from range cimport cpp_RangeBase
cdef extern from "ranges/ranges.h" namespace "CNORXZ":
cdef cppclass cpp_DIndex "CNORXZ::DIndex":
cpp_DIndex() except+
cpp_DIndex(const cpp_DIndex&) except+
cpp_DIndex(const shared_ptr[cpp_RangeBase]&, size_t lexpos) except+
cpp_DIndex setlpos "operator=" (size_t n) except+
cpp_DIndex setincr "operator++"() except+
cpp_DIndex setdecr "operator--"() except+
cpp_DIndex plus "operator+"(int n) except+
cpp_DIndex minus "operator-"(int n) except+
size_t lex() except+
size_t dim() except+
shared_ptr[cpp_RangeBase] range() except+
string stringMeta() except+
cdef extern from "ranges/ranges.h" namespace "CNORXZ":
cdef cppclass cpp_YIndex "CNORXZ::YIndex":
cpp_YIndex() except+
cpp_YIndex(const cpp_YIndex&) except+
cpp_YIndex(const shared_ptr[cpp_RangeBase]&, size_t lexpos) except+
cpp_YIndex setlpos "operator=" (size_t n) except+
cpp_YIndex setincr "operator++"() except+
cpp_YIndex setdecr "operator--"() except+
cpp_YIndex plus "operator+"(int n) except+
cpp_YIndex minus "operator-"(int n) except+
size_t lex() except+
size_t dim() except+
shared_ptr[cpp_RangeBase] range() except+
string stringMeta() except+

View file

@ -1,35 +1,36 @@
#include "cnorxz/core/include/array_wrapper.h" #include "array_wrapper.h"
using namespace CNORXZ using namespace CNORXZ;
static int PyCArrayB_init(CArrayWrapperBase* self, PyObject* args, PyObject* kwds) int PyCArrayB_init(PyCArrayB* self, PyObject* args, PyObject* kwds)
{ {
static char* kwlist[] = { "type", "extension" , NULL }; static char* kwlist[] = { "type", "extension" , NULL };
SizeT ext = 0; SizeT ext = 0;
const char* type; const char* type;
if(not PyArg_ParseTupleAndKeywords(args, kwds, "s|k", kwlist, &type, &ext)){ if(not PyArg_ParseTupleAndKeywords(args, kwds, "s|k", kwlist, &type, &ext)){
return NULL; return -1;
} }
if(ext != 0){ if(ext != 0){
RangePtr r = CRangeFactory(ext).create(); RangePtr r = CRangeFactory(ext).create();
self->ptrObj = new CArrayBase<T>(r); // TODO: different types!!!
self->ptrObj = new CArrayWrapper<Double>(r);
} }
else { else {
self->ptrObj = new CArrayBase<T>(); self->ptrObj = new CArrayWrapper<Double>();
} }
return 0; return 0;
} }
static void PyCArrayB_dealloc(CArrayWrapperBase* self) void PyCArrayB_dealloc(PyCArrayB* self)
{ {
delete self->ptrObject; delete self->ptrObj;
Py_TYPE(self)->tp_free(self); Py_TYPE(self)->tp_free(self);
} }
static PyObject* PyCArrayB_size(CArrayWrapperBase* self) PyObject* PyCArrayB_size(PyCArrayB* self)
{ {
if(not self->ptrObj->range()){ if(not self->ptrObj->range()){
PyErr_SetString(PyExc_RuntimeError, "array not initialized"); PyErr_SetString(PyExc_RuntimeError, "array not initialized");
@ -39,8 +40,27 @@ static PyObject* PyCArrayB_size(CArrayWrapperBase* self)
return Py_BuildValue("k",retval); return Py_BuildValue("k",retval);
} }
static PyMethodDef PyCArrayB_methods[] = { PyMethodDef PyCArrayB_methods[] = {
{ "size", (PyCFunction) PyCArrayB_size, METH_VARARGS, "return size of the array" }, { "size", (PyCFunction) PyCArrayB_size, METH_VARARGS, "return size of the array" },
{ NULL } { NULL }
}; };
PyTypeObject PyCArrayBType = { PyVarObject_HEAD_INIT(NULL,0) "cnorxz.CArray" };
PyTypeObject* PyCArrayBType_init()
{
PyCArrayBType.tp_new = PyType_GenericNew;
PyCArrayBType.tp_basicsize = sizeof(PyCArrayB);
PyCArrayBType.tp_dealloc = (destructor) PyCArrayB_dealloc;
PyCArrayBType.tp_flags = Py_TPFLAGS_DEFAULT;
PyCArrayBType.tp_doc = "cnorxz CArray wrapper";
PyCArrayBType.tp_methods = PyCArrayB_methods;
PyCArrayBType.tp_init = (initproc) PyCArrayB_init;
if(PyType_Ready(&PyCArrayBType) < 0) {
return NULL;
}
else {
return &PyCArrayBType;
}
}

View file

@ -1,11 +0,0 @@
from libcpp.memory cimport shared_ptr
from array cimport cpp_MArray
from range cimport cpp_RangeBase
cdef extern from "ranges/ranges.h" namespace "CNORXZ":
cdef cppclass cpp_RangeBase "CNORXZ::RangeBase":
size_t size() except +
size_t dim() except +
cpp_MArray[shared_ptr[cpp_RangeBase]] sub() except+

View file

@ -1,12 +0,0 @@
from libcpp.memory cimport shared_ptr
from range cimport cpp_RangeBase
cdef extern from "ranges/ranges.h" namespace "CNORXZ":
cdef cppclass cpp_RangeFactoryBase "CNORXZ::RangeFactoryBase":
shared_ptr[cpp_RangeBase] create() except +
cdef extern from "ranges/ranges.h" namespace "CNORXZ":
cdef cppclass cpp_CRangeFactory "CNORXZ::CRangeFactory" (cpp_RangeFactoryBase):
cpp_CRangeFactory(size_t size) except +
shared_ptr[cpp_RangeBase] create() except +

View file

@ -1,7 +1,8 @@
#!/usr/bin/env python #!/usr/bin/env python
import Cython.Build import Cython.Build
import setuptools #import setuptools
from distutils.core import setup, Extension
import sysconfig import sysconfig
import subprocess import subprocess
@ -25,6 +26,7 @@ if git_hash_tag == git_hash and expected_cnorxz_version != cnorxz_version:
inc_dirs = list() inc_dirs = list()
if path_to_cnorxz != "": if path_to_cnorxz != "":
inc_dirs.append( path_to_cnorxz + "/include/cnorxz" ) inc_dirs.append( path_to_cnorxz + "/include/cnorxz" )
inc_dirs.append( "cnorxz/core/include" )
lib_dirs = list() lib_dirs = list()
lib_dirs.append( "/usr/lib" ) lib_dirs.append( "/usr/lib" )
@ -53,25 +55,32 @@ if __name__ == "__main__":
for d in lib_dirs: for d in lib_dirs:
print("\t",d) print("\t",d)
extensions = list() #extensions = list()
extensions.append( #extensions.append(
setuptools.Extension( # setuptools.Extension(
name = libname + ".core", # #name = libname + ".core",
sources = [ # name = libname,
"cnorxz/core/core.pyx", # sources = [
], # "cnorxz/core/core.cpp",
define_macros=[('HAVE_CEREAL',None)], # "cnorxz/core/lib/array_wrapper.cpp"
**default_extension_args # ],
) # define_macros=[('HAVE_CEREAL',None)],
) # **default_extension_args
# )
#)
# append further extensions (cereal, hdf5, mpi ...) here # append further extensions (cereal, hdf5, mpi ...) here
setuptools.setup( setup(
name = libname, name = libname,
packages = setuptools.find_packages(), packages = setuptools.find_packages(),
version = version, version = version,
include_dirs = inc_dirs, include_dirs = inc_dirs,
ext_modules = Cython.Build.cythonize(extensions), ext_modules = [Extension(
'cnorxz', ['cnorxz/core/core.cpp','cnorxz/core/lib/array_wrapper.cpp'],
define_macros=[('HAVE_CEREAL',None)],
**default_extension_args
)],
#ext_modules = Cython.Build.cythonize(extensions),
author = author, author = author,
author_email = author_email, author_email = author_email,
) )