SWIG can handle this just fine. Make sure you define the interface in SWIG and then it won't be opaque. Here's a working example:
%module x
%inline %{
// Define the interface.
struct iExample
{
virtual int somePureVirtualMethod() = 0;
};
iExample* getMyClassInstance();
%}
// Implementation, not exposed to Python
%{
struct Internal : public iExample
{
int somePureVirtualMethod() { return 5; }
};
iExample* getMyClassInstance() { return new Internal(); }
%}
Demo:
>>> import x
>>> i = x.getMyClassInstance()
>>> i.somePureVirtualMethod()
5
However, this implementation will leak an Internal Instance. You may want to implement a way to free it automatically. One way is to use %newobject
and define a virtual destructor. Python will delete the object when there are no more references to it.
%module x
%newobject getMyClassInstance;
%inline %{
struct iExample
{
virtual ~iExample() {};
virtual int somePureVirtualMethod() = 0;
};
iExample* getMyClassInstance();
%}
// Implementation
%{
#include <iostream>
struct Internal : public iExample
{
int somePureVirtualMethod() { return 5; }
~Internal() { std::cout << "destroyed" << std::endl; }
};
iExample* getMyClassInstance() { return new Internal(); }
%}
Demo:
>>> import x
>>> i = x.getMyClassInstance()
>>> i.somePureVirtualMethod()
5
>>> i=2 # reassign i
destroyed # garbage-collected