13

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?

piotrMocz
  • 429
  • 4
  • 12
  • Shouldn't this work like explained for non-static methods in the documentation? http://docs.cython.org/src/userguide/wrapping_CPlusPlus.html#templates – m.s. Jun 29 '15 at 15:45
  • Unfortunately it doesn't. Writing `cdef extern from "Foo.h" namespace "Foo": shared_ptr[Foo[T]] doSth[T]()` doesn't work either. That's because cython generates C++ code like: `Foo::doSth();` -- the template parameter after Foo is missing. – piotrMocz Jun 29 '15 at 15:53

2 Answers2

10

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

robertwb
  • 4,891
  • 18
  • 21
  • Where the syntax "cdef ... = function" is described? I couldn't find it in Cython documentation. How can it be used if doSth has an argument? – proggamer12 Dec 03 '21 at 12:53
3

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...

Community
  • 1
  • 1
DavidW
  • 29,336
  • 6
  • 55
  • 86
  • Wrapping it works fine for me, thank you once again. I was just hoping I can avoid tinkering around my C++ code, but it's still super cool. I'll switch to the recommended way :) – piotrMocz Jun 29 '15 at 19:23