Swig C ++:接口vector< Class对象*> [英] Swig C++: Interfacing vector<Class object *>

查看:68
本文介绍了Swig C ++:接口vector< Class对象*>的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基本上,我试图在Python中有一个元组/列表,其中包含不同数据类型的值(float / int / bool / char / list)的数据字典。

basically I am trying to have a tuple/list which contains a dictionary of different data types of values(float/int/bool/char/list) in python.

我是从以下代码中获取的:

I am getting this from the following 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> >)

我想以以下形式获取输出:

I want to get the output in this form:


({'I':1.0,'B':2.0,'C':3.0,'dert _':[1.2,2.3,3.4,4.5,5.6]})

({'I':1.0,'B':2.0, 'C':3.0, 'dert_':[1.2, 2.3, 3.4, 4.5, 5.6]})

我无法处理此类对象指针(bunch *),也找不到任何解决方案。我在网上看了一下,但找不到适合我的案例的解决方案。

I ain't able to deal with this class object pointer (bunch*) and couldn't find any solution to it. I looked on the net but couldn't found a working solution for my case.

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))


推荐答案

问题真是沸腾了归结为:你有一个cl屁股,您想将其转换为原生Python对象(而不是包装对象)。 SWIG自动生成包装的对象,但是您必须竭尽全力将C ++类型转换为本地Python类型。

The question really boils down to this: you have a class and you'd like to convert it a native Python object (rather than a wrapped object). SWIG automatically generates wrapped objects but you have to go out of your way to convert C++ types to native Python types.

I我假设使用简化的 Bunch 使类型映射更具可读性。您应该可以很容易地将其适应您的 Bunch 。或者,您可以在将类传递给Python之前将其转换为该简单结构。

I'm assuming this simplified Bunch to make the typemap a little more readable. You should be able to adapt this to your Bunch quite easily. Alternatively, you could convert your class to this simple struct before passing it on to Python.

struct Bunch {
    float i, b, c;
    std::vector<float> dert;
};

Bunch makeBunch();

这是 makeBunch 的实现。

Bunch makeBunch() {
    return {1.0, 2.0, 3.0, {1.2, 2.3, 3.4, 4.5, 5.6}};
}

我省略了错误检查以使其简洁明了。

I've omitted error checking to keep it short and concise.

%typemap(out) Bunch {
    $result = PyDict_New();
    PyDict_SetItem($result, PyBytes_FromString("I"), PyFloat_FromDouble($1.i));
    PyDict_SetItem($result, PyBytes_FromString("B"), PyFloat_FromDouble($1.b));
    PyDict_SetItem($result, PyBytes_FromString("C"), PyFloat_FromDouble($1.c));
    PyObject *dert = PyList_New($1.dert.size());
    for (size_t i = 0; i != $1.dert.size(); ++i) {
        PyList_SetItem(dert, i, PyFloat_FromDouble($1.dert[i]));
    }
    PyDict_SetItem($result, PyBytes_FromString("dert_"), dert);
}

当我自己编译并运行此程序时,我得到了预期的结果(嗯,

When I compile and run this myself, I get the expected results (well, close enough!).

>>> import test
>>> test.makeBunch()
{'I': 1.0, 'C': 3.0, 'B': 2.0, 'dert_': [1.2000000476837158, 2.299999952316284, 3.4000000953674316, 4.5, 5.599999904632568]}






类型映射并非严格必要。您可以只使用包装的对象。删除类型映射,并确保像这样暴露 std :: vector< float>

%include "std_vector.i"
%template(FloatVector) std::vector<float>;

然后您可以通过包装访问 Bunch

Then you can access Bunch via a wrapped object.

>>> import test
>>> bunch = test.makeBunch()
>>> bunch
<test.Bunch; proxy of <Swig Object of type 'Bunch *' at 0x10b6daba0> >
>>> bunch.i
1.0
>>> bunch.b
2.0
>>> bunch.c
3.0
>>> bunch.dert
<test.FloatVector; proxy of <Swig Object of type 'std::vector< float,std::allocator< float > > *' at 0x10b6dadb0> >
>>> for d in bunch.dert:
...     print(d)
...
1.20000004768
2.29999995232
3.40000009537
4.5
5.59999990463






一些知名来源:


Some reputable sources:

  • Typemaps
  • PyDict
  • PyBytes
  • PyFloat
  • PyList

这篇关于Swig C ++:接口vector&lt; Class对象*&gt;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆