Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cython C++ static methods in a template class

Problem

I have a template class in C++ that has a static method. It looks more or less like this:

template<typename T>
class Foo {
    static std::shared_ptr<Foo<T>> doSth();
}

so in C++ you would call it like: Foo<Int>::doSth();. In Cython however, the way to call static methods is by using the classname as a namespace:

cdef extern from "Bar.h" namespace "Bar":
    shared_ptr[Bar] doSth()  # assuming shared_ptr is already declared

but this has no notion of templates. Obviously, simply passing Foo<T> as a namespace doesn't work, because it translates to Foo<T>::doStr() in C++, no concrete type is substituted for T.

Question

How would you do that in Cython? Is there a way, or a workaround?

like image 844
piotrMocz Avatar asked Jun 29 '15 15:06

piotrMocz


People also ask

What are static templates and static variables in C++?

Templates and Static variables in C++. Function templates and static variables: Each instantiation of function template has its own copy of local static variables. For example, in the following program there are two instances: void fun(int ) and void fun(double ). So two copies of static variable i exist.

Should I add static types to my Cython code?

However, for performance critical code, it is often helpful to add static type declarations, as they will allow Cython to step out of the dynamic nature of the Python code and generate simpler and faster C code - sometimes faster by orders of magnitude.

How many static variables are there in an instantiation of class?

Class templates and static variables: Each instantiation of class template has its own copy of member static variables. For example, in the following program there are two instances Test and Test. So two copies of static variable count exist.

How do I use C data types in Python syntax?

To make use of C data types in Python syntax, you need to import the special cython module in the Python module that you want to compile, e.g. Cython is a Python compiler. This means that it can compile normal Python code without changes (with a few obvious exceptions of some as-yet unsupported language features, see Cython limitations ).


2 Answers

Static methods are now directly supported by Cython; the namespace hack is no longer necessary or recommended.

cdef extern from "Foo.h":
    cdef cppclass Foo[T]:
        @staticmethod
        shared_ptr[Foo[T]] doSth()  # assuming shared_ptr is already declared

cdef shared_ptr[Foo[int]] shared_ptr_value = Foo[int].doSth()

http://docs.cython.org/en/latest/src/userguide/wrapping_CPlusPlus.html#static-member-method

like image 109
robertwb Avatar answered Oct 23 '22 07:10

robertwb


Note: This answer was right at the time it was written (and does still work) but you should now use @Robertwb's answer to this question instead to do this properly.


I don't think you can do it directly in Cython. You could create very thin wrapper of a normal (non-static-method) c++ template function

template <typename T>
std::shared_ptr<Foo<T>> Foo_T_doSth<T>() {
   return Foo<T>::doSth();
}

and then wrap this method in Cython

cdef extern from "..."
    shared_ptr[T] Foo_T_doSth[T]()

As an aside, the recommended way of wrapping static methods in Cython looks to be (from https://groups.google.com/forum/#!topic/cython-users/xaErUq2yY0s)

cdef extern from "...":
   cdef Foo_doSth "Foo::doSth"()  # not declared as a memeber

(by specifying the actual function to use as a string). This doesn't help you here because it doesn't cope with templates. It may have been me who mis-advised you on the way you were trying...

like image 34
DavidW Avatar answered Oct 23 '22 07:10

DavidW