Cython: extending Python standard library classes - cython

I am very new to Cyhon and have very little experience with C, but I am testing Cython by refactoring an existing module I wrote.
I am not sure how I should extend a Python standard library class. this:
from contextlib import ContextDecorator
cdef class MyCtxManager(ContextDecorator):
# override methods
gives me an error:
'ContextDecorator' is not a type name
How do I extend ContextDecorator into a Cython class?

Related

I want to call cdef function which takes cpp type as argument using python interpreter

I'm generating different .pyx files and turning them to C++ .so libraries. So I got an example generatedLib.pyx like this:
from libcpp.vector cimport vector
def cinit(self): pass
cdef public void someFunction(vector[...]& inputs):
...
The public function always has same signature, except for the name. I somehow wanna call this public function using python interpreter because I prefer to write tests in Python rather than C++. I cannot do it directly of course. I cannot define this function as def as well since its parameter is of C++ vector type.
I have came up with an idea to have a wrapper function
def wrapperSomeFunction(input: list)
{
# convert Python list to c++ vector
someFunction(v)
# convert c++ vector back to python list and return
}
I can import the generatedLib as python module and call this wrapper just fine, it requires however, to append it to my generatedFile.pyx file contents every time I wanna test it before I build it. I would rather look for alternative solutions.
Is there some way I can build a separate .pyx which will have this wrapper inside and will be able to call my generatedLib.so? Or perhaps something else I didn't think of?

How to write C++ constructor of cython extension type?

How do I modify the C++ class constructor that cython will generate from a Cython extension type that I've defined in a .pyx file wo that I don't incur the penalty of using def __cinit__(self)? Assume I am compiling to C++, not C.
What I would like to do is set the default values as I would in an initialization list in C++, and maybe run some code in the constructor without interacting with Python. It looks like the __cinit__ method runs after the C++ class members are initialized and the C++ constructor finishes running.
In this example, it says
Cython initializes C++ class attributes of a cdef class using the nullary constructor.
I assume this refers to the default constructor since the C++ constructor is a nullary constructor. I also assumes this happens with or without a __cinit__ method.
If the class you’re wrapping does not have a nullary constructor, you must store a pointer to the wrapped class and manually allocate and deallocate it. A convenient and safe place to do so is in the cinit and dealloc methods which are guaranteed to be called exactly once upon creation and deletion of the Python instance.
I have an existing class where I call Py_XDECREF on a member object in a loop inside of __dealloc__. This object holds pointers to Python objects. When I convert to C++ code, the annotated HTML shows no highlighted yellow text in the lines where the __dealloc__ method is defined. This is interesting because __dealloc__ is also defined using def.
When I try to initialize a member that is an instance of a Cython Extension that I defined (and did not create from wrapping C++ code), however, the __cinit__ method is highlighted in yellow.
def __cinit__(self):
self._member = MyCyExt()
I'm wondering if it's because I can't initialize a Cython Extension Type in pure C++. I don't know why that would be the case since Cython calls the nullary constructor by default.
This answer solves the problem, but it incurs the overhead I am trying to avoid. Is there a way to do this without incurring that overhead and actually writing the constructor itself in a .pyx file?

How to call a virtual method overridden in python from C++ using SWIG

My C++ class:
class Base {
public:
virtual void foo(int);
};
In the python module, I have a class that derives from above and overrides foo.
class PyDerived(Base):
...
def foo(self):
...
Then I create an object of this derived class using a factory method that is defined in python module like this:
def createObject():
m = PyDerived()
return m
With this PyObject in C++ code, I want to call foo and I want foo in python module to be executed. Is this possible? If so how?
(I already tried calling virtual methods from python which dispatch the actual call to a C++ method, but that does not match my requirements)
Yes, you need to enable the SWIG "directors" feature for the class Base containing the virtual method. You can read about it in the documentation here.
The documentation will tell you that you need to add two things to the SWIG interface file:
At the very beginning, edit the %module directive to enable the use of directors at all:
%module(directors="1") your_modulename
Before the declaration of the class Base or the corresponding %include directive, put the following to enable the directors feature for that class:
%feature("director") Base;

Jruby rb to java generated class inheritance support or workarounds

I am experimenting around with JRuby - generating java from ruby files. I have an abstract class in ruby that implement a Java interface, and child classes extending this. also in ruby.
I'm running into the problem as described on http://jira.codehaus.org/browse/JRUBY-6342 where all the generated java files only extend RubyObject.
I am wondering if anyone else has encountered this and have a workaround? Right now I have used a java_implement interface in each child class as they do not extend the abstract class.
I have included the snippet from JRUBY-6342 describing the problem:
The Java code generated by jrubyc --java does not appear to support Ruby class inheritance. Given the following simple example:
class A
def my_class; self.class.name end
end
class B < A
end
The generated class in B.java inherits from RubyObject rather than A, rendering the B class completely broken in Java.
On a somewhat related note, module inclusion doesn't seem to work either. A class with include M doesn't get M's methods in the generated Java code.
Am I missing something in my understanding of Ruby or JRuby?
This is still an issue indeed as the jruby compiler still produces RubyObject for the classes.
The only workaround that I know to this is to use the JRuby ScriptEngine from Java to eval your JRuby code. For example, here is some JRuby code:
require 'java'
java_import 'javax.swing.JFrame'
java_import 'javax.swing.JButton'
class MyFrame < JFrame
def initialize
super('Test')
content_pane.add(JButton.new("Hello"))
pack()
end
end
This code can then be called from a Java class like this:
import javax.swing.JFrame;
import javax.script.*;
import java.io.*;
public class Main {
public static void main(String[] args) throws Exception {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("jruby");
Reader reader = new FileReader("myframe.rb");
engine.eval(reader);
// Instantiate the JRuby class, and cast the result of eval.
JFrame frame = (JFrame) engine.eval("MyFrame.new");
frame.setVisible(true);
}
}
Here the object returned by eval can be casted into JFrame, just as you would expect. See also this question for that problem.

SWIG: generate additional (hand-rolled) Java class

I'm using SWIG to generate a Java JNI wrapper for my DLL.
As part of it, I want to generate a custom exception class, but I want to provide the complete Java class implementation for my exception class myself.
I can of course just put my Java class in a separate file, but is it possible to embed such a hand-rolled Java class into a SWIG script?
Unless the class is an inner class of some sort you're pretty much left with writing it as a separate file since that's what it needs to be when you come to compile the Java.
I'm slightly puzzled why you would want to write your own pure Java exception class though - the normal thing to do with SWIG would be derive from std::exception, even if it's through a %inline directive and merge the C++ exception hierarchy with the Java one naturally and for free.
There is a workaround you could use if you really want (although I personally would neverdo it) to generate a pure Java class from the SWIG interface though:
%module test
%nodefaultctor MyException;
%typemap(javabody) MyException %{
// Java stuff goes here (or in javacode typemap)
%}
%typemap(javafinalize) MyException ""
%typemap(javadestruct) MyException ""
struct MyException {};
Which generates:
public class MyException {
// stuff goes here
}
But since that is clearly an ugly hack I'd strongly recommend avoiding it entirely and just writing the class like normal in your source distribution.