I think in the future we'll support fused cdef class attributes, e.g.
cdef class MyClass:
cdef framed_multi[cython.floating] obj
which might be specialized through constructor arguments or indexing the class.
For now you might be stuck with methods, attributed with faked types
and casting. I wrote a little snippet that lets you specialize by
indexing the class using slightly hacky code. It basically uses a
metaclass that when indexed returns a subclass where all the methods
are specialized. You will still have to cast self.vector to the right
specialized type and you have to use a dummy argument for each method,
but at least it should be somewhat more comfortable to deal with.
Of course, the ideal thing to do would be to fix Cython :) If you want
to fix this issue in Cython, we'd be happy to give you pointers and
help. This will be supported, but the developers are busy with their
lives and don't really desperately need it, so it's hard to tell when.
################## test.pyx
cimport cython
import inspect
import functools
cdef extern from "multivector.h":
cdef cppclass multivector[T]:
int method()
ctypedef multivector[cython.floating] multivector_floating_t
def wrap(func):
@functools.wraps(func)
def wrapper(self, *a, **kw):
return func(self, 0.0, *a, **kw,)
return wrapper
cdef class _MultiVector:
cdef multivector[float] *vector
def method(self, cython.floating dummy, *args, **kwargs):
cdef multivector_floating_t *actual_vector =
<multivector_floating_t *> self.vector
print actual_vector.method()
print args, kwargs
class Meta(type):
_cache = {}
def __getitem__(cls, specialization):
if specialization in cls._cache:
return cls._cache[specialization]
print "getitem"
name = specialization.capitalize() + cls.__name__
newcls = type(name, (cls,), {})
for name, attribute in inspect.getmembers(cls):
if hasattr(attribute, '__signatures__'):
# function has a fused dummy argument
setattr(newcls, name, wrap(attribute[specialization]))
cls._cache[specialization] = newcls
return newcls
class MultiVector(_MultiVector):
__metaclass__ = Meta
obj = MultiVector["float"]()
obj.method(10, kw=20)
obj = MultiVector["double"]()
obj.method(10, kw=20)
################# multivector.h
template <class T>
class multivector {
T attrib;
public:
int method() {
return sizeof(attrib);
}
};
Well, the third option is to use your own home-made templatesto
auto-generate cython code for each type. That's actually not as
painful as it sounds -- there are lot's of templating systems for
python -- Cheetah, for instance is designed for "any" use, not just
html (though I'm never used it for Cython).
http://www.cheetahtemplate.org/
You might want to look at the "bottleneck" project -- they did
something like this -- not for calling a C++ templates, but the
principle is the same.
http://berkeleyanalytics.com/bottleneck/