Calling a function of an object instance using embedded Python - python

I want to be able to run Python scripts in my app to allow automating stuff and modifying existing objects/calling methods of existing objects.
In my application there is a BasicWindow class and MainWindow class that derives from the former. For now at application start I initialize one instance of MainWindow. This object has many functions, among them there is one that loads files (LoadFile()), and I will use it as example here.
Lets say that I want to call that particular function (but not limited to that function, it is just an example of the functionality that I want to achieve from Python) of that particular object instance.
This method is not a static one. For this I am using Boost.Python and I am creating a module this way:
BOOST_PYTHON_MODULE(MyModule)
{
MainWindow::PythonExpose(); //not really sure how to operate here
//more stuff
}
The idea is that I could call from Python something like:
MainWindow.LoadFile()
or even better, just:
LoadFile()
One solution could be to create static, application scoped functions and then just expose those functions. In C++ I could find the particular instance of MainWindow: (both methods are static)
void AppHelper::LoadFile()
{
GetMainWindow()->LoadFile();
}
void AppHelper::PythonExposeGlobal()
{
using namespace boost::python;
def("LoadFile", &AppHelper::LoadFile);
}
Is it possible to achieve this? The general question would be: is it possible to call methods of existing objects (in C++) from Python? If so, how to do it? If not, what can I do to mimic this behavior?
For example, I could easily enable scripting capabilities in my C# application and sharing instances of existing objects. (But of course C# has reflection).

If you can guarantee that the object will live as long as any scripts using it run, then there's a fairly simple approach that I use.
I'll use a primitive counter class for demonstration:
class counter
{
public:
counter() : count(0) {}
void increment() { ++count; }
int count;
};
Now, I expose this class to python, such that it considers it non-copyable, and doesn't allow construction of new instances. I also expose any members that I want to use from the scripts.
BOOST_PYTHON_MODULE(example)
{
bp::class_<counter, boost::noncopyable>("Counter", bp::no_init)
.def("increment", &counter::increment)
;
}
Next step is to create a Python object that uses an existing instance, and allow the script to use it (e.g. add it as an attribute of some module, such as the main one).
counter c;
bp::object main_module(bp::import("__main__"));
main_module.attr("c") = bp::object(bp::ptr(&c));
Now your scripts can use this instance:
c.increment()
Sample program:
#include <boost/python.hpp>
#include <iostream>
namespace bp = boost::python;
// Simple counter that can be incremented
class counter
{
public:
counter() : count(0) {}
void increment() { ++count; }
int count;
};
// Expose the counter class to Python
// We don't need constructor, since we only intend to use instance
// already existing on the C++ side
BOOST_PYTHON_MODULE(example)
{
bp::class_<counter, boost::noncopyable>("Counter", bp::no_init)
.def("increment", &counter::increment)
;
}
int main()
{
Py_InitializeEx(0);
// Bind our class
initexample();
counter c;
bp::object main_module(bp::import("__main__"));
bp::object main_namespace(main_module.attr("__dict__"));
// Add the current instance of counter to Python as attribute c of the main module
main_module.attr("c") = bp::object(bp::ptr(&c));
std::cout << "Before: " << c.count << '\n';
// Increment the counter from Python side
bp::exec("c.increment()", main_namespace);
std::cout << "After: " << c.count << '\n';
Py_Finalize();
return 0;
}
Console Output:
Before: 0
After: 1

Related

Down Casting and Template Solution Vs Python

this is basic C++ but I am getting to a point where python actually seems way simpler. Suppose:
class Base
{
public:
virtual ~Base() = default;
virtual std::string type() const { return "base"; };
};
class Derived1 : public Base
{
public:
virtual std::string type() const { return "dervied1"; };
};
class Derived2 : public Base
{
public:
virtual std::string type() const { return "dervied2"; };
};
I find my self having other functions of type:
void process(Base& derived_from_base)
{
};
Q1: How do I know what I am taking as input, should I call type() and later down cast, problem is I think type() will give always "base"?
Q2: This is so annoying. I later have to down case the input to the correct derived class. I am just wondering if python is doing this in the background, am I sure that with all of this I am faster than python?
Q3: Is it true I can replace virtual function/inheritance and all casting using templates? (heard this somewhere and not sure).
Thank you very much.
Q1: How do I know what I am taking as input?
A1: Keep the full type instead of erasing it to the base class. E.g. instead of
void process(Base& base) {
if (base.type() == "derived1") process_derived1(static_cast<Derived1&>(base));
else process_anything_else(base);
}
int main() {
std::unique_ptr<Base> base = std::make_unique<Derived1>();
process(*base);
}
use
void process(Derived1& derived1) { process_derived1(derived1); }
void process(auto& t) { process_anything_else(t); }
int main() {
Derived derived1;
process(derived1);
}
Q2: I am just wondering if python is doing this in the background, am I sure that with all of this I am faster than python?
A2: Python has something like this:
int main() {
Object derived1; // a hash map
derived1["__type__"] = "Derived1";
}
With the approach from A1, you are faster than anything (assuming everything else in the program isn't worse) because of static dispatch: thanks to templates, overload resolution happens at compile time and therefore costs nothing.
Q3: Is it true I can replace virtual function/inheritance and all casting using templates? (heard this somewhere and not sure)
A3: With proper design, you can do that most of the times, e.g. see A1. However, some things force linking dynamically: OS API, game plugins etc. In such cases, consider localizing the clumsy borderline part, so most of the code can be written as usual.
virtual function/inheritance
Note: inheritance without virtual functions is perfectly fine and zero-cost (on its own), e.g. see CRTP.

How do I stop pybind11 from deallocating an object constructed from Python?

So, I know that pybind lets you set a return value policy for methods that you wrap up. However, that doesn't seem to be working for me when I try to use this policy on a constructor. I have a class to wrap my C++ type that looks like this:
class PyComponent{
public:
static Component* Create(ComponentType type) {
Component* c = new Component(type);
// Irrelevant stuff removed here
return c;
}
/// #brief Wrap a behavior for Python
static void PyInitialize(py::module_& m);
};
void PyComponent::PyInitialize(py::module_ & m)
{
py::class_<Component>(m, "Component")
.def(py::init<>(&PyComponent::Create), py::return_value_policy::reference)
;
}
However, this does NOT stop my Component type from getting deallocated from the Python side if I call Component() and the created object goes out of scope. Any suggestions?
I did figure out the solution to this. It's to pass py::nodelete to the wrapper for my class
void PyComponent::PyInitialize(py::module_ & m)
{
py::class_<Component, std::unique_ptr<Component, py::nodelete>>(m, "Component")
.def(py::init<>(&PyComponent::Create), py::return_value_policy::reference)
;
}

Calling C++ class functions from Ruby/Python

In my specific circumstance, I have a complex class (a class of classes of classes) that I want to expose to a scripting language (aka Ruby). Rather that directly pass that complex class, someone gave me the idea of just opening up a few functions to a scripting language like Ruby, which seemed simpler. I've seen Rice but the only examples I've seen use simple functions that just multiply something, rather than interfacing with a class.
For simplicity, I have a simple class with functions I want to expose:
class Foo
{
private:
//Integer Vector:
std::vector<int> fooVector;
public:
//Functions to expose to Ruby:
void pushBack(const int& newInt) {fooVector.push_back(newInt);}
int& getInt(const int& element) {return fooVector.at(element);}
};
ALSO:
I'd prefer not to just have a link to the download page of SWIG, or an article explaining how to do this with rice that was written in 2010, I would like a guide that will likely work (I haven't had much luck just yet)
ASWELL:
I'm using Linux (Ubuntu) but this is a cross-compatible program, so I must be able to compile on Windows and OS X
EDIT:
I do understand that shared libraries exist (dll and so files), but I don't know if I can have a library that depends on a .hpp file containing the class(es).
You can use cython or Boost.Python to call native code from python. Since you are using c++, i'd recommend looking into Boost.Python which offers a very natural way of wrapping c++ classes for python.
As an example (close to what you provided), consider the following class definitions
class Bar
{
private:
int value;
public:
Bar() : value(42){ }
//Functions to expose to Python:
int getValue() const { return value; }
void setValue(int newValue) { value = newValue; }
};
class Foo
{
private:
//Integer Vector:
std::vector<int> fooVector;
Bar bar;
public:
//Functions to expose to Python:
void pushBack(const int& newInt) { fooVector.push_back(newInt); }
int getInt(const int& element) { return fooVector.at(element); }
Bar& getBar() { return bar; }
};
double compute() { return 18.3; }
This can be wrapped to python using Boost.Python
#include <boost/python.hpp>
BOOST_PYTHON_MODULE(MyLibrary) {
using namespace boost::python;
class_<Foo>("Foo", init<>())
.def("pushBack", &Foo::pushBack, (arg("newInt")))
.def("getInt", &Foo::getInt, (arg("element")))
.def("getBar", &Foo::getBar, return_value_policy<reference_existing_object>())
;
class_<Bar>("Bar", init<>())
.def("getValue", &Bar::getValue)
.def("setValue", &Bar::setValue, (arg("newValue")))
;
def("compute", compute);
}
This code can be compiled to a static library MyLibrary.pyd and used like this
import MyLibrary
foo = MyLibrary.Foo()
foo.pushBack(10);
foo.pushBack(20);
foo.pushBack(30);
print(foo.getInt(0)) # 10
print(foo.getInt(1)) # 20
print(foo.getInt(2)) # 30
bar = foo.getBar()
print(bar.getValue()) # 42
bar.setValue(17)
print(foo.getBar().getValue()) #17
print(MyLibrary.compute()) # 18.3
What about Boost.Python?
How come you don't want to use SWIG?

Wrapping an std::vector using boost::python vector_indexing_suite

I am working on a C++ library with Python bindings (using boost::python) representing data stored in a file. Majority of my semi-technical users will be using Python to interact with it, so I need to make it as Pythonic as possible. However, I will also have C++ programmers using the API, so I do not want to compromise on the C++ side to accommodate Python bindings.
A large part of the library will be made out of containers. To make things intuitive for the python users, I would like them to behave like python lists, i.e.:
# an example compound class
class Foo:
def __init__( self, _val ):
self.val = _val
# add it to a list
foo = Foo(0.0)
vect = []
vect.append(foo)
# change the value of the *original* instance
foo.val = 666.0
# which also changes the instance inside the container
print vect[0].val # outputs 666.0
The test setup
#include <boost/python.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include <boost/python/register_ptr_to_python.hpp>
#include <boost/shared_ptr.hpp>
struct Foo {
double val;
Foo(double a) : val(a) {}
bool operator == (const Foo& f) const { return val == f.val; }
};
/* insert the test module wrapping code here */
int main() {
Py_Initialize();
inittest();
boost::python::object globals = boost::python::import("__main__").attr("__dict__");
boost::python::exec(
"import test\n"
"foo = test.Foo(0.0)\n" // make a new Foo instance
"vect = test.FooVector()\n" // make a new vector of Foos
"vect.append(foo)\n" // add the instance to the vector
"foo.val = 666.0\n" // assign a new value to the instance
// which should change the value in vector
"print 'Foo =', foo.val\n" // and print the results
"print 'vector[0] =', vect[0].val\n",
globals, globals
);
return 0;
}
The way of the shared_ptr
Using the shared_ptr, I can get the same behaviour as above, but it also means that I have to represent all data in C++ using shared pointers, which is not nice from many points of view.
BOOST_PYTHON_MODULE( test ) {
// wrap Foo
boost::python::class_< Foo, boost::shared_ptr<Foo> >("Foo", boost::python::init<double>())
.def_readwrite("val", &Foo::val);
// wrap vector of shared_ptr Foos
boost::python::class_< std::vector < boost::shared_ptr<Foo> > >("FooVector")
.def(boost::python::vector_indexing_suite<std::vector< boost::shared_ptr<Foo> >, true >());
}
In my test setup, this produces the same output as pure Python:
Foo = 666.0
vector[0] = 666.0
The way of the vector<Foo>
Using a vector directly gives a nice clean setup on the C++ side. However, the result does not behave in the same way as pure Python.
BOOST_PYTHON_MODULE( test ) {
// wrap Foo
boost::python::class_< Foo >("Foo", boost::python::init<double>())
.def_readwrite("val", &Foo::val);
// wrap vector of Foos
boost::python::class_< std::vector < Foo > >("FooVector")
.def(boost::python::vector_indexing_suite<std::vector< Foo > >());
}
This produces:
Foo = 666.0
vector[0] = 0.0
Which is "wrong" - changing the original instance did not change the value inside the container.
I hope I don't want too much
Interestingly enough, this code works no matter which of the two encapsulations I use:
footwo = vect[0]
footwo.val = 555.0
print vect[0].val
Which means that boost::python is able to deal with "fake shared ownership" (via its by_proxy return mechanism). Is there any way to achieve the same while inserting new elements?
However, if the answer is no, I'd love to hear other suggestions - is there an example in the Python toolkit where a similar collection encapsulation is implemented, but which does not behave as a python list?
Thanks a lot for reading this far :)
Due to the semantic differences between the languages, it is often very difficult to apply a single reusable solution to all scenarios when collections are involved. The largest issue is that the while Python collections directly support references, C++ collections require a level of indirection, such as by having shared_ptr element types. Without this indirection, C++ collections will not be able to support the same functionality as Python collections. For instance, consider two indexes that refer to the same object:
s = Spam()
spams = []
spams.append(s)
spams.append(s)
Without pointer-like element types, a C++ collection could not have two indexes referring to the same object. Nevertheless, depending on usage and needs, there may be options that allow for a Pythonic-ish interface for the Python users while still maintaining a single implementation for C++.
The most Pythonic solution would be to use a custom converter that would convert a Python iterable object to a C++ collection. See this answer for implementation details. Consider this option if:
The collection's elements are cheap to copy.
The C++ functions operate only on rvalue types (i.e., std::vector<> or const std::vector<>&). This limitation prevents C++ from making changes to the Python collection or its elements.
Enhance vector_indexing_suite capabilities, reusing as many capabilities as possible, such as its proxies for safely handling index deletion and reallocation of the underlying collection:
Expose the model with a custom HeldType that functions as a smart pointer and delegate to either the instance or the element proxy objects returned from vector_indexing_suite.
Monkey patch the collection's methods that insert elements into the collection so that the custom HeldType will be set to delegate to a element proxy.
When exposing a class to Boost.Python, the HeldType is the type of object that gets embedded within a Boost.Python object. When accessing the wrapped types object, Boost.Python invokes get_pointer() for the HeldType. The object_holder class below provides the ability to return a handle to either an instance it owns or to an element proxy:
/// #brief smart pointer type that will delegate to a python
/// object if one is set.
template <typename T>
class object_holder
{
public:
typedef T element_type;
object_holder(element_type* ptr)
: ptr_(ptr),
object_()
{}
element_type* get() const
{
if (!object_.is_none())
{
return boost::python::extract<element_type*>(object_)();
}
return ptr_ ? ptr_.get() : NULL;
}
void reset(boost::python::object object)
{
// Verify the object holds the expected element.
boost::python::extract<element_type*> extractor(object_);
if (!extractor.check()) return;
object_ = object;
ptr_.reset();
}
private:
boost::shared_ptr<element_type> ptr_;
boost::python::object object_;
};
/// #brief Helper function used to extract the pointed to object from
/// an object_holder. Boost.Python will use this through ADL.
template <typename T>
T* get_pointer(const object_holder<T>& holder)
{
return holder.get();
}
With the indirection supported, the only thing remaining is patching the collection to set the object_holder. One clean and reusable way to support this is to use def_visitor. This is a generic interface that allows for class_ objects to be extended non-intrusively. For instance, the vector_indexing_suite uses this capability.
The custom_vector_indexing_suite class below monkey patches the append() method to delegate to the original method, and then invokes object_holder.reset() with a proxy to the newly set element. This results in the object_holder referring to the element contained within the collection.
/// #brief Indexing suite that will resets the element's HeldType to
/// that of the proxy during element insertion.
template <typename Container,
typename HeldType>
class custom_vector_indexing_suite
: public boost::python::def_visitor<
custom_vector_indexing_suite<Container, HeldType>>
{
private:
friend class boost::python::def_visitor_access;
template <typename ClassT>
void visit(ClassT& cls) const
{
// Define vector indexing support.
cls.def(boost::python::vector_indexing_suite<Container>());
// Monkey patch element setters with custom functions that
// delegate to the original implementation then obtain a
// handle to the proxy.
cls
.def("append", make_append_wrapper(cls.attr("append")))
// repeat for __setitem__ (slice and non-slice) and extend
;
}
/// #brief Returned a patched 'append' function.
static boost::python::object make_append_wrapper(
boost::python::object original_fn)
{
namespace python = boost::python;
return python::make_function([original_fn](
python::object self,
HeldType& value)
{
// Copy into the collection.
original_fn(self, value.get());
// Reset handle to delegate to a proxy for the newly copied element.
value.reset(self[-1]);
},
// Call policies.
python::default_call_policies(),
// Describe the signature.
boost::mpl::vector<
void, // return
python::object, // self (collection)
HeldType>() // value
);
}
};
Wrapping needs to occur at runtime and custom functor objects cannot be directly defined on the class via def(), so the make_function() function must be used. For functors, it requires both CallPolicies and a MPL front-extensible sequence representing the signature.
Here is a complete example that demonstrates using the object_holder to delegate to proxies and custom_vector_indexing_suite to patch the collection.
#include <boost/python.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
/// #brief Mockup type.
struct spam
{
int val;
spam(int val) : val(val) {}
bool operator==(const spam& rhs) { return val == rhs.val; }
};
/// #brief Mockup function that operations on a collection of spam instances.
void modify_spams(std::vector<spam>& spams)
{
for (auto& spam : spams)
spam.val *= 2;
}
/// #brief smart pointer type that will delegate to a python
/// object if one is set.
template <typename T>
class object_holder
{
public:
typedef T element_type;
object_holder(element_type* ptr)
: ptr_(ptr),
object_()
{}
element_type* get() const
{
if (!object_.is_none())
{
return boost::python::extract<element_type*>(object_)();
}
return ptr_ ? ptr_.get() : NULL;
}
void reset(boost::python::object object)
{
// Verify the object holds the expected element.
boost::python::extract<element_type*> extractor(object_);
if (!extractor.check()) return;
object_ = object;
ptr_.reset();
}
private:
boost::shared_ptr<element_type> ptr_;
boost::python::object object_;
};
/// #brief Helper function used to extract the pointed to object from
/// an object_holder. Boost.Python will use this through ADL.
template <typename T>
T* get_pointer(const object_holder<T>& holder)
{
return holder.get();
}
/// #brief Indexing suite that will resets the element's HeldType to
/// that of the proxy during element insertion.
template <typename Container,
typename HeldType>
class custom_vector_indexing_suite
: public boost::python::def_visitor<
custom_vector_indexing_suite<Container, HeldType>>
{
private:
friend class boost::python::def_visitor_access;
template <typename ClassT>
void visit(ClassT& cls) const
{
// Define vector indexing support.
cls.def(boost::python::vector_indexing_suite<Container>());
// Monkey patch element setters with custom functions that
// delegate to the original implementation then obtain a
// handle to the proxy.
cls
.def("append", make_append_wrapper(cls.attr("append")))
// repeat for __setitem__ (slice and non-slice) and extend
;
}
/// #brief Returned a patched 'append' function.
static boost::python::object make_append_wrapper(
boost::python::object original_fn)
{
namespace python = boost::python;
return python::make_function([original_fn](
python::object self,
HeldType& value)
{
// Copy into the collection.
original_fn(self, value.get());
// Reset handle to delegate to a proxy for the newly copied element.
value.reset(self[-1]);
},
// Call policies.
python::default_call_policies(),
// Describe the signature.
boost::mpl::vector<
void, // return
python::object, // self (collection)
HeldType>() // value
);
}
// .. make_setitem_wrapper
// .. make_extend_wrapper
};
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
// Expose spam. Use a custom holder to allow for transparent delegation
// to different instances.
python::class_<spam, object_holder<spam>>("Spam", python::init<int>())
.def_readwrite("val", &spam::val)
;
// Expose a vector of spam.
python::class_<std::vector<spam>>("SpamVector")
.def(custom_vector_indexing_suite<
std::vector<spam>, object_holder<spam>>())
;
python::def("modify_spams", &modify_spams);
}
Interactive usage:
>>> import example
>>> spam = example.Spam(5)
>>> spams = example.SpamVector()
>>> spams.append(spam)
>>> assert(spams[0].val == 5)
>>> spam.val = 21
>>> assert(spams[0].val == 21)
>>> example.modify_spams(spams)
>>> assert(spam.val == 42)
>>> spams.append(spam)
>>> spam.val = 100
>>> assert(spams[1].val == 100)
>>> assert(spams[0].val == 42) # The container does not provide indirection.
As the vector_indexing_suite is still being used, the underlying C++ container should only be modified using the Python object's API. For instance, invoking push_back on the container may cause a reallocation of the underlying memory and cause problems with existing Boost.Python proxies. On the other hand, one can safely modify the elements themselves, such as was done via the modify_spams() function above.
Unfortunately, the answer is no, you can't do what you want. In python, everything is a pointer, and lists are a container of pointers. The C++ vector of shared pointers work because the underlying data structure is more or less equivalent to a python list. What you are requesting is to have the C++ vector of allocated memory act like a vector of pointers, which can't be done.
Let's see what's happening in python lists, with C++ equivalent pseudocode:
foo = Foo(0.0) # Foo* foo = new Foo(0.0)
vect = [] # std::vector<Foo*> vect
vect.append(foo) # vect.push_back(foo)
At this point, foo and vect[0] both point to the same allocated memory, so changing *foo changes *vect[0].
Now with the vector<Foo> version:
foo = Foo(0.0) # Foo* foo = new Foo(0.0)
vect = FooVector() # std::vector<Foo> vect
vect.append(foo) # vect.push_back(*foo)
Here, vect[0] has it's own allocated memory, and is a copy of *foo. Fundamentally, you can't make vect[0] be the same memory as *foo.
On a side note, be careful with lifetime management of footwo when using std::vector<Foo>:
footwo = vect[0] # Foo* footwo = &vect[0]
A subsequent append may require moving the allocated storage for the vector, and may invalidate footwo (&vect[0] may change).

How do I invoke a method on a C++ class pointer with swig wrappers?

I'm using SWIG to wrap C++ code for use within a Python testing framework. My problem is that I'm getting a pointer to an instance of a class that I need to then invoke methods on. Eg, within my swig file example.i:
iExample* getMyClassInstance();
...
class iExample
{
public:
virtual void somePureVirtualMethod() = 0;
// ...
};
Now, in python, if I had the class, I could just call the method
myClassInstance.somePureVirtualMethod()
However, I don't actually have an instance of the class, of course. I have an opaque pointer generated from SWIG. How do I use it? Obviously in Python I can't do
myClassInstancePtr = example.getMyClassInstance()
myClassInstancePtr->somePureVirtualMethod()
I tried using cpointer.i or pointer.i in swig to generate pointer functions, but that's no good, because it's trying to create copies of the class. This can't even compile with an interface with pure virtual methods, and even if I wasn't using pure virtual methods, I don't want to create a copy of the class, I just want to invoke something on it!
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
The simplest answer I've found is to edit your example.i to add in some helper functions to do dereferencing. In your swig file example.i:
{%
...
// Helper function to dereference pointers within python
template <typename T>
T& dereference(T* ptr)
{
return *ptr;
}
...
%}
...
// Make every version of the templated functions we'll need
template <typename T> T& dereference(T* ptr);
%template(dereferencePtr_iExample) dereference<iExample>;
Now in python
myClassInstance = example.dereferencePtr_iExample(example.getMyClassInstance())
myClassInstance.somePureVirtualMethod()
I imagine this method should work generically for other languages like perl as well, and you don't have to screw around with SWIG typemaps.

Categories