I have some C++ I have exposed to Python through SWIG. In there is a base class with a single pure virtual function.
In Python, I import my module and define a class that uses the abstract class as base.
import mymodule
class Foo(mymodule.mybase):
...
In that module is also a manager class, I want to add my new defined class to the manager.
m = mymodule.mymanager()
m.add(Foo())
Definition of add:
void add(mybase* b) { ... }
Didn't work as I would expect:
TypeError: in method 'mymanager_add', argument 2 of type 'mymodule::mybase *'
What did I miss? It seems it's not sure that my Foo class is a "mybase". I tried adding a call to the base class constructor in Python but that didn't work, said the class was abstract.
def __init__(self):
mymodule.mybase.__init__(self)
My guess is that Foo is not derived from mybase in the eyes of the C++ environment. I'm not sure if SWIG can pull this off since it requires a bidirectional understanding of inheritance - Python class uses C++ class as base and C++ code recognizes the inheritance relationship. I would take a serious look into Boost.python since it seems to support the functionality that you are after. Here's an entry on wiki.python.org about it.
Not really an answer, but you might have better luck with boost.python. Don't know how much work it would be for you to switch, but you could probably get a simple inheritence test case for your problem going pretty quickly.
Related
I have abstract class which has few implemented protected methods and few abstract methods.
I am trying to write some tests for the protected methods.
Since these are not available even in the extended classes to outside world, I would like to create anonymous Test class which can extend and verify/mock my stuff.
export abstract class AbsClass implements AbsInterface {
protected extract(filter: string) {
//some implemented code to test
}
abstract someMethod();
}
I am not able to figure out how to create something like this anonymously
export class TestClass extends AbsClass {
public testExtract(){
//call super.extract and verify result
}
}
I've run into this before. It seems like the export/abstract keywords interfere with each other. I've had to define the class and then export on a separate line to get around this.
Example:
abstract class BaseClass {}
export default BaseClass
There are some workarounds discussed in this related issue. See also:
https://github.com/microsoft/TypeScript/issues/36060
https://github.com/microsoft/TypeScript/issues/17293
https://github.com/microsoft/TypeScript/issues/35822
The short answer is that it's very difficult to represent anonymous classes that access private/protected members of their superclass right now. If you're just trying to test parts of the superclass, does the implementing class really have to be anonymous?
(As an aside: I'm still pretty new at testing generally, but I've seen a lot of strongly worded advice about not explicitly testing private/protected methods. Would it be preferable to test the public API methods that call the private/protected ones instead?)
I have a class that inherits from boost::statechart library. I need to use this class in Python script, I am wondering if I need to write wrapper codes (.def s) for all boost::statechart library just because my class inherited from it? Or the boost.python will not need any wrapper code to see the definitions (it handles other boost libraries automatically to call in python)?
Boost.Python does not have any special handling for Boost classes. If you want to use inherited functions (Boost class or not), you need to expose them to Python like you would do with your own code.
If you don't want to use any of the base class functions from your script, you need not do anything besides binding your own code.
You have two options if you need (some of) the base class interface available from Python:
You bind the base class separately and expose it as a base for your class. This is the most "complete" solution (as complete as you make it - you can choose to limit the number of exposed functions).
You don't bind the base class. Python does not have to know about the inheritance relationship. You can simply bind the functions you want to expose as all public functions are members of the derived class, too. This is simpler if you only need some of the base class functionality to be usable from Python.
For a project, I am being asked to create a VST using the Steinberg SDK, i'm using version 2.4.
The issue that I'm having is error:
cannot allocate an object of abstract type 'mySynth'.
When attempting to compile, the error brings me to this section of code:
AudioEffect* createEffectInstance (audioMasterCallback audioMaster)
{
return new mySynth (audioMaster);
}
I'm a beginner to both c++ and VST programming, I've had no issues compiling the sample AGain and ADelay, as well as the vstxSynth. This is the first attempt of my own, and its really confusing me, from looking at the sample code i cannot seem to find any reason as to why this shouldn't work.
any help would be greatly appreciated. As this is a major learning curve for me, i would appreciate if you could apply with a simplest explanations as possible.
Thankyou :)
Without seeing the class mySynth code it is hard to say but this error is commonly encountered when you have a class containing a pure virtual function. Either that or you have derived from a base class with a pure virtual function and have failed to override it with a derived class implementation.
If you do not know what that means, look in your class (and sub classes) for functions declared like this
virtual int my_function() = 0;
This kind of function is a pure virtual function and a class that has one is considered an abstract class and cannot be instantiated. In order to do so you would need to provide an implementation.
Your processReplacing() method is not correctly overriding signature declared in the base class AudioEffect. The signature looks like this:
void processReplacing(float** inputs, float** outputs, VstInt32 sampleFrames);
Your override is using double, it should use float instead.
I have a C++ project that use a lot of classes. The main one is 'sso::Object' (every classes are in the 'sso' namespace) and this class is derived into some other classes but one which is abstract: 'sso::Drawable'.
This class has two pure virtual methods 'sso::Drawable::set_opacity' and 'sso::Drawable::raw_draw' and it is derived into other classes like 'sso::View' which implement these two methods.
The whole project works fine when it is used in C++, but I would like to use it in Python too, so I created a Boost.Python module like that:
class DrawableWrapper : public sso::Drawable , public wrapper<sso::Drawable> {
public:
void set_opacity(byte opacity) { this->get_override("set_opacity")(opacity); }
void raw_draw(const sso::Rect &rect,sso::Target &target,const sso::Position &position) const {
this->get_override("raw_draw")(rect,target,position);
}
};
BOOST_PYTHON_MODULE(sso) {
class_<DrawableWrapper,boost::noncopyable> ("Drawable",init<>())
.add_property ("opacity",&sso::Drawable::get_opacity)
// python_sso_getter & python_sso_setter_* are only used for an easier access to accessors
.add_property ("position",python_sso_getter<sso::Drawable,sso::Position,&sso::Drawable::get_position>,python_sso_setter_1_const<sso::Drawable,sso::Position,&sso::Drawable::set_position>)
.def("raw_draw",pure_virtual(&sso::Drawable::raw_draw))
;
class_<sso::View,bases<sso::Drawable> > ("View",init<>())
.def("insert",python_sso_setter_1<sso::View,sso::Drawable*,&sso::View::insert>)
.def("remove",&sso::View::erase)
;
}
This code compile without errors but when I execute these lines in Python:
myview = sso.View()
print myview
I get this output:
<sso.View object at 0x7f9d2681a4b0>
But my C++ debugger tell me that the variable 'v' (the python 'myview') is a 'sso::Object' instance, not a 'sso::View' one. sso::View::View() is called but the variable type is not a view and I don't know why. Do you have any idea about that ? Did you do something like that and found a way to make it work ?
I use Python2.7 and Boost.Python1.49 and gcc version 4.6.1
EDIT: I've made a mistake: sso::Drawable does not inherit from sso::Object, but sso::View does (=multiple inheritance).
The output <sso.View object at 0x7f9d2681a4b0> from python is just python telling you what it thinks the object type is called, it has nothing to do with the actual type of object created at the C++ level.
As you've told boost python to expose the object as sso.View then that is what python will see it as. If you were to change your code to expose std::string as sso.View then python would still report <sso.View object at 0x7f9d2681a4b0> after you've created it.
Similarly, if you were to change "View" in your C++ to "BlahDeBlah" then python would report the object as <sso.BlahDeBlah object at 0x7f9d2681a4b0> (of course you'd also have to create it via sso.BlahDeBlah()
That aside, I can't see anything wrong with the code you have posted. Does sso::View inherit from sso::Object? If that's the case, and you've witnessed sso::view::View() being called, then I think you might just be misinterpreting the debugger when it tells you the object is of type sso::Object. Perhaps it has a pointer to the base class or something similar at the point you are debugging?
What happens when you call myview.insert or myview.remove from python?
EDIT: I suspect (though I could be wrong) that you might not have RTTI turned on in your compiler, so typeid() is just returning the type that implemented the function you are in when you called typeid(). That would certainly explain why you get sso::View when in insert but a different answer in other functions.
Anyway, I've been looking into the documentation a little bit more and I think your problem is actually that you've provided the ability to override the raw_draw method but you haven't actually overridden it with anything.
If you have a look at the decleration of the pure_virtual boost::python function at the bottom of this file you'll see a comment:
//
// Passed a pointer to member function, generates a def_visitor which
// creates a method that only dispatches to Python if the function has
// been overridden, either in C++ or in Python, raising a "pure
// virtual called" exception otherwise.
//
So what you're seeing is just expected behaviour. If you provide an override for raw_draw in sso::View or a python class that inherits from it then you should no longer get this error.
I have a class in C++ that I can't modify. However, that class holds an std::list<> of items that I need to be able to access in a Python extension. Since Boost::Python doesn't seem to have a built-in conversion between an std::list and a Python list, I was hoping to be able to write a method in C++ that could do this conversion for me and later, when I am mapping the C++ classes to Python classes, I could attach this method.
I would prefer if I could just call the method like
baseClassInstance.get_std_list_of_items_as_python_list()
To answer the question in a more general way, you can attach any c++ function that has the right signature to the python export in the class_ declaration.
assume a class foo:
struct foo
{
//class stuff here
}
You can define a free function that takes a reference to foo as the first argument:
int do_things_to_a_foo(foo& self, int a, std::string b, other_type c)
{
//Do things to self
}
And export it just like a member of foo:
class_<foo>("foo")
...
.def("do_things_to_a_foo", &do_things_to_a_foo)
...
;
Boost provides a helper to wrap iterators which is documented here: http://www.boost.org/doc/libs/1_42_0/libs/python/doc/v2/iterator.html
The example hear the end of that page worked for me, you just need to explicitly create the conversion, for example:
class_<std::list<Item> >("ItemList")
.def("__iter__", iterator<std::list<Item> >());
To modify the C++ class without changing it, I am in the habit of creating a thin wrapper that subclasses the real class. This makes a nice place to separate out all the crud that makes my C++ objects feel comfortable from Python.
class Py_BaseClass : public BaseClass {
public:
std::list<Item> & py_get_items();
}