How to pass python list address

此生再无相见时 提交于 2019-12-25 18:28:05

问题


I want to convert c++ code to python. I have created a python module using SWIG to access c++ classes.

Now I want to pass the following c++ code to Python

C++

#define LEVEL 3
  double thre[LEVEL] = { 1.0l, 1.0e+2, 1.0e+5 };
  GradedDouble gd(LEVEL, thre);
  gd.avg(thre);

I need to convert the above code to python

C++ constructor used for generating python module

GradedDouble::GradedDouble(int n, double *thre)
{
  n_ = n;
  for (int i = 0; i < n_; ++i)
  {
    thre_.push_back(thre[i]);
    grade_.push_back(new grade_type());
  }
}

SWIG interface file

/* File: example.i */

%module example
%include typemaps.i
%apply double * INPUT { double *}
%apply double * INPUT { double *buf };

%{
#include "Item.h"
#include "GradedComplex.h"
#include "GradedDouble.h"
void avg(double *buf);
%}

%include <std_string.i>
%include <std_complex.i>
%include "Item.h"
%include "GradedComplex.h"
%include "GradedDouble.h"
%template(Int) Item<int>;
%template(Double) Item<double>;
%template(Complex) Item<std::complex<double> >;

A sample python module function

class GradedDouble(_object):
    __swig_setmethods__ = {}
    __setattr__ = lambda self, name, value: _swig_setattr(self, GradedDouble, name, value)
    __swig_getmethods__ = {}
    __getattr__ = lambda self, name: _swig_getattr(self, GradedDouble, name)
    __repr__ = _swig_repr
    def __init__(self, *args): 
        this = _example.new_GradedDouble(*args)
        try: self.this.append(this)
        except: self.this = this
    __swig_destroy__ = _example.delete_GradedDouble
    __del__ = lambda self : None;
    def push(self, *args): return _example.GradedDouble_push(self, *args)
    def avg(self, *args): return _example.GradedDouble_avg(self, *args)
GradedDouble_swigregister = _example.GradedDouble_swigregister
GradedDouble_swigregister(GradedDouble)

How do I convert it?


回答1:


Using raw double * and length as an interface is more difficult in SWIG. You'd need to write a typemap for the parameter pair that can intelligently read the array given the size. Easier to use SWIG's built-in vector support.

Example, with display support:

GradedDouble.i

%module GradedDouble

%{
#include "GradedDouble.h"
%}

%include <std_vector.i>
%include <std_string.i>
%template(DoubleVector) std::vector<double>;
%rename(__repr__) ToString;
%include "GradedDouble.h"

GradedDouble.h

#include <vector>
#include <string>
#include <sstream>

class GradedDouble
{
    std::vector<double> thre_;
public:
    GradedDouble(const std::vector<double>& dbls) : thre_(dbls) {}
    ~GradedDouble() {}
    std::string ToString() const
    {
        std::ostringstream ss;
        ss << "GradedDouble(";
        for(auto d : thre_)
            ss << ' ' << d;
        ss << " )";
        return ss.str();
    }
};

Output

>>> import GradedDouble as gd
>>> x=gd.GradedDouble([1.2,3.4,5.6])
>>> x
GradedDouble( 1.2 3.4 5.6 )



回答2:


Another method for doing this is by using SWIG cpointer and carrays. Sample code is below:

Interface file:

%module example
%include "cpointer.i"
%{
#include "Item.h"
#include "GradedDouble.h"
extern void avg(double *buf);
%}
%pointer_class(double, doublep);

%include "carrays.i"
%array_class(double, doubleArray);
%include <std_string.i>
%include "Item.h"
%include "GradedDouble.h"
%template(Double) Item<double>;

Python code:

LEVEL = 3
thre = [1, 100, 10000]
a = example.doubleArray(LEVEL)
for i in xrange(LEVEL):
    a[i] = thre[i]

gd=example.GradedDouble(LEVEL,a)

result = example.doublep()
gd.avg(result)
print result.value()

This worked for me



来源:https://stackoverflow.com/questions/13410691/how-to-pass-python-list-address

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!