Grundsätzlich versuche ich, ein Tupel / eine Liste zu haben, die ein Wörterbuch mit verschiedenen Datentypen von Werten (float / int / bool / char / list) in Python enthält.
Ich erhalte dies aus dem folgenden Code:
(<f_p.Bunch; proxy of <Swig Object of type 'Bunch *' at 0x7f4954bdde10> >, <f_p.Bunch; proxy of <Swig Object of type 'Bunch *' at 0x7f4954bdde40> >, <f_p.Bunch; proxy of <Swig Object of type 'Bunch
*' at 0x7f495668be70> >, <f_p.Bunch; proxy of <Swig Object of type 'Bunch *' at 0x7f4952d09a50> >)
Ich möchte die Ausgabe in dieser Form erhalten:
({'I': 1,0, 'B': 2,0, 'C': 3,0, 'dert _': [1,2, 2,3, 3,4, 4,5, 5,6]})
Ich kann mit diesem Klassenobjektzeiger (Haufen *) nicht umgehen und konnte keine Lösung dafür finden. Ich habe im Internet gesucht, aber keine funktionierende Lösung für meinen Fall gefunden.
f_p.cpp:
#include <iostream>
#include "f_p.h"
#define CPP_14 0
std::vector<Bunch*> form_p(const double *array, int x, int y) {
std::vector<Bunch*> v;
Bunch *b1 = new Bunch(5);
b1->set_I_B_C(1.0, 2.0, 3.0);
b1->set_dert_({1.2, 2.3, 3.4, 4.5, 5.6});
float *_dert = b1->get_dert_();
for(int i=0; i<5; i++) {
std::cout << _dert[i] << std::endl;
}
v.push_back(b1);
v.push_back(b1);
v.push_back(b1);
v.push_back(b1);
return v;
}
f_p.h:
#ifndef F_P_H
#define f_P_H
#include <memory>
#include <vector>
#include <memory>
#include <algorithm>
#include <tuple>
#include <initializer_list>
class Bunch {
private:
unsigned int start;
unsigned int end;
float I;
float B;
float C;
bool isPos;
std::unique_ptr<float[]> dert_;
public:
explicit Bunch(size_t width) {
#if CPP_14
this->dert_ = std::make_unique<float[]>(width);
#else
this->dert_ = std::unique_ptr<float[]>(new float[width]);
#endif
std::fill_n(this->dert_.get(), width, -1.0);
}
void set_I_B_C(float I, float B, float C) {
this->I = I;
this->B = B;
this->C = C;
}
std::tuple<float, float, float> get_I_B_C() const {
return std::make_tuple(this->I, this->B, this->C);
}
float* get_dert_() const {
return this->dert_.get();
}
void set_dert_(std::initializer_list<float> l) {
int i = 0;
for (auto e: l){
dert_[i++] = e;
}
}
};
/* Define function prototype */
std::vector<Bunch*> form_p(const double *array, int x, int y) ;
#endif
f_p.i:
%module f_p
#define SWIGPYTHON_BUILTIN
%{
#include "numpy/arrayobject.h"
#define SWIG_FILE_WITH_INIT /* To import_array() below */
#include "f_p.h"
%}
%include "std_map.i"
%import "std_deque.i"
%import "std_vector.i"
%template (mapiv) std::map<char,float>;
%template () std::vector<Bunch*>;
%include "numpy.i"
%init %{
import_array();
%}
%apply (double* IN_ARRAY2, int DIM1, int DIM2) {
(const double* array, int x, int y)
}
%include "f_p.h"
build.sh:
rm *.o f_p_wrap.cpp _f_p.so f_p.py
rm -rf __pycache__
g++ -O3 -march=native -fPIC -c f_p.cpp
swig -python -c++ -o f_p_wrap.cpp f_p.i
# Next, compile the wrapper code:
g++ -O3 -march=native -w -fPIC -c $(pkg-config --cflags --libs python3) -I /home/antpc/anaconda3/lib/python3.7/site-packages/numpy/core/include f_p.cpp f_p_wrap.cpp
g++ -std=c++11 -O3 -march=native -shared f_p.o f_p_wrap.o -o _f_p.so -lm
test_sample.py:
from f_p import form_p
import numpy as np
x = np.random.randn(3, 4)
print(form_p(x))
typemap(out)
für erstellen möchtenBunch
. Warumform_p
kehrtstd::vector<Bunch *>
statt stattstd::vector<Bunch>
? Swig wird diese Zeiger nicht freigeben, sodass Sie Speicher verlieren.Antworten:
Die Frage läuft wirklich darauf hinaus: Sie haben eine Klasse und möchten sie in ein natives Python-Objekt (anstatt in ein umschlossenes Objekt) konvertieren. SWIG generiert automatisch umschlossene Objekte, aber Sie müssen sich alle Mühe geben, um C ++ - Typen in native Python-Typen zu konvertieren.
Ich gehe davon aus, dass dies vereinfacht ist
Bunch
, um die Typkarte etwas lesbarer zu machen. Sie sollten diesBunch
ganz einfach an Ihre Bedürfnisse anpassen können. Alternativ können Sie Ihre Klasse in diese einfache Struktur konvertieren, bevor Sie sie an Python weitergeben.Hier ist die Implementierung von
makeBunch
.Ich habe die Fehlerprüfung weggelassen, um sie kurz und prägnant zu halten.
Wenn ich dies selbst kompiliere und ausführe, erhalte ich die erwarteten Ergebnisse (na ja, nah genug!).
Die Typkarte ist nicht unbedingt erforderlich. Sie können stattdessen einfach umschlossene Objekte verwenden. Entfernen Sie die Typzuordnung und stellen Sie sicher, dass Sie sie
std::vector<float>
wie folgt belichten .Dann können Sie
Bunch
über ein umschlossenes Objekt zugreifen .Einige seriöse Quellen:
quelle