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?
Related
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.
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)
;
}
Swig generates wrapper code for a object member that has not default constructor.
Code to wrap:
class Foo {
public:
Foo (int i);
};
Class Bar {
public:
Bar(int i):foo(i)
{
...
}
Foo foo;
};
Swig Setter generated:
SWIGINTERN PyObject *_wrap_Bar_foo_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
Bar *arg1 = (Bar *) 0 ;
Foo arg2 ; // -> swig generates a call to a non existing default constructor
...
Then, if a try to compile the wrapper, I get an error since the default contructor does not exist:
error: no matching function for call to ‘Foo::Foo()’
Please note, the same approach is done for the getter generation.
How can I tell swig to generate a setter that accepts Foo* or Foo&?
Thanks,
Pablo
SWIG fundamentally supports this just fine, in fact I can't actually reproduce what you've seen with the code you showed. For example, this all works:
%module test
%inline %{
class Foo {
public:
Foo (int i) {}
};
class Bar {
public:
Bar(int i):foo(i)
{
}
Foo foo;
};
%}
When compiled and run with SWIG 3.0.2 (which is pretty old these days!) lets me run this Python code:
import test
f=test.Foo(0)
b=test.Bar(0)
b.foo=f
print('Well that all worked ok')
The reason this can work, even in the more general cases, is because of a feature known as the "Fulton Transform". In essence this is intended to work around a lack of copy constructor by wrapping it inside another object instead. (Although in the specific instance you've shown it's not actually needed even).
Anyway, although this should apply automatically there are a few cases were it can't won't. Fortunately though you can force this on even when it doesn't work automatically, using %feature
All you need to do is include, within your .i file, somewhere before first declaration/definition of a type without a copy ctor the following:
%feature("valuewrapper") Foo;
And that's it.
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.
Do CPython has something similar to .net c# PInvoke?
For example I have some.dll or some.so and would like to register some functions from it on runtime and start using those in my program.
In C# you can do:
// Marshal.cs
using System;
using System.Runtime.InteropServices;
namespace CSharpIterators
{
class MainClass
{
[DllImport("msvcrt.dll")]
public static extern int puts([MarshalAs(UnmanagedType.LPStr)] string m);
[DllImport("msvcrt.dll")]
internal static extern int _flushall();
public static void Main (string[] args)
{
puts("Hello World!");
_flushall();
}
}
}
Do python has similar functionality?
Thanks in advance!
You can call functions from DLLs using Python's ctypes module.
Another option is to use tools like swig in order to create a Python interface to C/C++ code:
http://www.swig.org/
The syntax for creating the wrappers is very similar to C plus some preprocessing directives.