Seite 1 von 1
C++ Klasse in Python importieren
Verfasst: Mi Nov 07, 2012 6:33 pm
von Glocke
Ich habe eine (aus meiner Sicht) "schöne" Möglichkeit gefunden, in C++ implementierte Klassen in Python zu importieren: SWIG.
example.hpp
Code: Alles auswählen
#ifndef EXAMPLE_H
#define EXAMPLE_H
class Foo {
protected:
int value;
public:
double bar;
Foo(int value);
void set_value(int value);
int get_value();
};
#endif
example.cpp
Code: Alles auswählen
#include "example.hpp"
Foo::Foo(int value) {
this->value = value;
this->bar = 1.0;
}
void Foo::set_value(int value) {
this->value = value;
}
int Foo::get_value() {
return this->value;
}
example.i
Code: Alles auswählen
%module example
%{
#define SWIG_FILE_WITH_INIT
#include "example.hpp"
%}
%include "example.hpp"
Und gebaut habe ich das so:
swig -c++ -python example.i
g++ -fPIC -c example.cpp example_wrap.cxx -I/usr/include/python2.7/
g++ -shared example_wrap.o example.o -o _example.so
Dabei entstehen
example.py und
_example.so. Offensichtlich sind beide notwendig um das Modul
example in Python zu importieren.
Code: Alles auswählen
Python 2.7.3 (default, Aug 1 2012, 05:16:07)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from example import Foo
>>> f = Foo(15)
>>> f.bar
1.0
>>> f.value
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "example.py", line 74, in <lambda>
__getattr__ = lambda self, name: _swig_getattr(self, Foo, name)
File "example.py", line 55, in _swig_getattr
raise AttributeError(name)
AttributeError: value
>>> f.get_value()
15
>>> f.set_value(12)
>>> f.get_value()
12
>>> f.set_value(12.4)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "example.py", line 83, in set_value
def set_value(self, *args): return _example.Foo_set_value(self, *args)
TypeError: in method 'Foo_set_value', argument 2 of type 'int'
Dabei werden offenbar auch Typsicherheit und Sichtbarkeit beibehalten.
Was sagt ihr dazu, ist das so sinnvoll?
LG Glocke
Re: C++ Klasse in Python importieren
Verfasst: Di Jan 08, 2013 9:48 am
von Glocke
Hey, ich muss das ganze mal erweitern. Anbei etwas sinnloser Beispielcode (C++):
http://pastebin.com/J0SpBnC7 und
http://pastebin.com/FTC4Vv17.
Dazu die "Engine.i" für SWIG:
Code: Alles auswählen
%module Engine
%include "std_string.i"
%include "std_map.i"
%{
#define SWIG_FILE_WITH_INIT
#include "Engine.hpp"
%}
%include "Engine.hpp"
Gebaut habe ich mit:
Code: Alles auswählen
#!/bin/bash
clear
echo "Fetch from C++"
swig -c++ -python $1.i
echo "Compile Source"
g++ -fPIC -c $1.cpp $1_wrap.cxx -I/usr/include/python2.7/
echo "Link as Library"
g++ -shared $1_wrap.o $1.o -o _$1.so
echo "Done"
und dann "./build Engine"
Und ausgeführt (in der Python Konsole) folgendes:
http://pastebin.com/03x7Xh7r
Ich schaffe es nicht, der map etwas zuzuweisen ... Was mache ich falsch?
LG Glocke
Re: C++ Klasse in Python importieren
Verfasst: Di Jan 08, 2013 10:42 am
von Xin
Bitte kein Pastebin. Kopiert den Kram
bitte in das Posting und im Idealfall liefert ein ZIP-Archiv mit, damit man den Kram nicht einzeln sich irgendwo zusammenklauben muss, wenn man es zum Testen selbst bauen will!
Example.hpp
Code: Alles auswählen
#include <iostream>
#include "Engine.hpp"
Engine::Engine(const std::string name, int limit) {
this->user = new User(name);
this->limit = limit;
}
Engine::~Engine() {
delete this->user;
}
void Engine::run() {
while (!(this->user->finished(this->limit))) {
this->user->inc();
}
}
User::User(const std::string name) {
this->name = name;
this->counter = 0;
}
void User::inc() {
this->counter += 1;
std::cout << "New value is of '" << this->name << "' is " << this->counter << std::endl;
}
bool User::finished(int limit) {
return (this->counter >= limit);
}
Example.cpp
Code: Alles auswählen
#include <iostream>
#include "Engine.hpp"
Engine::Engine(const std::string name, int limit) {
this->user = new User(name);
this->limit = limit;
}
Engine::~Engine() {
delete this->user;
}
void Engine::run() {
while (!(this->user->finished(this->limit))) {
this->user->inc();
}
}
User::User(const std::string name) {
this->name = name;
this->counter = 0;
}
void User::inc() {
this->counter += 1;
std::cout << "New value is of '" << this->name << "' is " << this->counter << std::endl;
}
bool User::finished(int limit) {
return (this->counter >= limit);
}
Konsoleneingaben:
Code: Alles auswählen
[Python 2.7.3 (default, Aug 1 2012, 05:16:07)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from Engine import Engine, User
>>> e = Engine("glocke", 12)
>>> e.run()
New value is of 'glocke' is 1
New value is of 'glocke' is 2
New value is of 'glocke' is 3
New value is of 'glocke' is 4
New value is of 'glocke' is 5
New value is of 'glocke' is 6
New value is of 'glocke' is 7
New value is of 'glocke' is 8
New value is of 'glocke' is 9
New value is of 'glocke' is 10
New value is of 'glocke' is 11
New value is of 'glocke' is 12
>>> u = User("foobar")
>>> print u.foo
<Swig Object of type 'std::map< int,std::string,std::less< int >,std::allocator< std::pair< int const,std::string > > > *' at 0xb7209908>
>>> u.foo[2] = "Zwei"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'SwigPyObject' object does not support item assignment
>>> u.foo.append(2, "Zwei")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: append() takes exactly one argument (2 given)
>>> u.foo.append((2, "Zwei"))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
SystemError: error return without exception set
Laut
CPlusPlus.com unterstützt std::map gar kein append. Wie sieht's mit
insert aus?
Ansonsten arbeitet die STL gerne mit Iteratoren. Du müsstest also nicht einen Index übergeben, sondern den passenden Iterator, z.B. u.foo.end().
Re: C++ Klasse in Python importieren
Verfasst: Di Jan 08, 2013 3:02 pm
von Glocke
Xin hat geschrieben:Bitte kein Pastebin. Kopiert den Kram bitte in das Posting
Okay Chef
Xin hat geschrieben:Laut
CPlusPlus.com unterstützt std::map gar kein append. Wie sieht's mit
insert aus?
Ansonsten arbeitet die STL gerne mit Iteratoren. Du müsstest also nicht einen Index übergeben, sondern den passenden Iterator, z.B. u.foo.end().
Ich war auch verwundert. Aber laut Python-Funktion "dir()" hat u.foo kein begin, end, insert oder so, aber ein append, next und owns ...

Re: C++ Klasse in Python importieren
Verfasst: Di Jan 08, 2013 3:15 pm
von Xin
Glocke hat geschrieben:Ich war auch verwundert. Aber laut Python-Funktion "dir()" hat u.foo kein begin, end, insert oder so, aber ein append, next und owns ...

Kurz gegooglet und bei swig.org gelandet.
std::map wird wohl deutlich bearbeitet, bevor es an Python rausgeht.
Es gibt wohl ein da einige Includes (
http://www.swig.org/Doc1.3/Library.html ... pp_library), die man sich mal ansehen müsste.
Re: C++ Klasse in Python importieren
Verfasst: Di Jan 08, 2013 3:36 pm
von cloidnerux
Code: Alles auswählen
>>> u.foo.append(2, "Zwei")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: append() takes exactly one argument (2 given)
append kann doch nur 1 Element anfügen, also müsste der Aufruf doch so aussehen:
Re: C++ Klasse in Python importieren
Verfasst: Mi Jan 09, 2013 8:33 am
von Glocke
Xin hat geschrieben:std::map wird wohl deutlich bearbeitet, bevor es an Python rausgeht.
Wahrscheinlich fahre ich eh besser, wenn ich zum modifizieren der std::map ne Methode verwende und die map als protected deklariere, oder?
Re: C++ Klasse in Python importieren
Verfasst: Mi Jan 09, 2013 10:55 am
von Xin
Glocke hat geschrieben:Xin hat geschrieben:std::map wird wohl deutlich bearbeitet, bevor es an Python rausgeht.
Wahrscheinlich fahre ich eh besser, wenn ich zum modifizieren der std::map ne Methode verwende und die map als protected deklariere, oder?
Ich vermute es, aber vom Prinzip solltest Du Dir erst anschauen, was Dir swig so anbietet.