如何传递python列表地址

Posted

技术标签:

【中文标题】如何传递python列表地址【英文标题】:How to pass python list address 【发布时间】:2012-11-16 04:53:58 【问题描述】:

我想将 c++ 代码转换为 python。 我使用 SWIG 创建了一个 python 模块来访问 c++ 类。

现在我想将以下 c++ 代码传递给 Python

C++

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

我需要把上面的代码转换成python

用于生成python模块的C++构造函数

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 接口文件

/* 文件: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> >;

一个示例python模块函数

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)

如何转换?

【问题讨论】:

我试图传递一个 python 列表的地址。但它似乎不正确 转换为 Python 与与 Python 交互不同(好吧,不是我所说的那样)。看来您希望将代码与 Python 接口。至于 COpython 的评论:您没有显示任何表明尝试使用 SWIG 或 Python C API 的代码;只有 C++ 代码。如您所说,如果您有一个使用 SWIG 的 Python 模块,请向我们展示更多您已经拥有的代码。 @Evert 添加了 SWIG 接口文件和示例 python 模块函数 【参考方案1】:

在 SWIG 中使用原始双 * 和长度作为接口更加困难。您需要为参数对编写一个类型映射,该类型映射可以智能地读取给定大小的数组。更容易使用 SWIG 的内置矢量支持。

示例,支持显示:

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

输出

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

【讨论】:

【参考方案2】:

另一种方法是使用 SWIG cpointer 和 carrays。示例代码如下:

接口文件:

%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 代码:

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

这对我有用

【讨论】:

以上是关于如何传递python列表地址的主要内容,如果未能解决你的问题,请参考以下文章

深入理解Python列表(list)

如何在 Python 中将列表作为函数的输入传递

如何在 SWIG/Python 中将结构列表传递给 C

将 Python 列表传递给 php

Python:当列表仅在运行时确定时,如何将可迭代列表传递给 zip?

在 C++ 中嵌入 Python。传递接收列表列表的字符串向量