使用Swig传递指向缓冲区的指针会导致“ TypeError”

时间:2019-01-25 19:24:07

标签: python c swig

我们有一个嵌入式系统,可以对数据缓冲区进行处理。当缓冲区已满时,中断触发处理。期望用模拟的输入数据来测试算法。我们的数据科学团队使用Python,并且该算法是用C语言开发的,因此我愿意为它们创建一个包装器。

问题围绕着传递给算法的缓冲区的指针。

作为一个简单的示例,C函数看起来像这样:

float FakeCalc( unsigned int *dataBuffer,
                 float *calcSpace,
                 int    arg1,
                 float  arg2,
                 int    arg3,
                 int    arg4,
                 int   *intermediateResults
               );

我创建了如下的SWIG接口文件:

%module fakeCalc

%include "typemaps.i"
%apply unsigned int * INPUT { unsigned int * dataBuffer };
%apply float * INOUT { float * calcSpace };
%apply int * OUTPUT { int * intermediateResults };

%{
extern float FakeCalc( unsigned int * dataBuffer,
                 float * calcSpace,
                 int     winAvgSz,
                 float   eleMulSign,
                 int     denomWindNum,
                 int     winSz,
                 int   * intermediateResults
               );
%}

extern float FakeCalc( unsigned int * dataBuffer,
                 float * calcSpace,
                 int     winAvgSz,
                 float   eleMulSign,
                 int     denomWindNum,
                 int     winSz,
                 int   * intermediateResults
               );

这创建了界面,所以我觉得我很高兴。

一个简单的python测试测试实现,如下所示:

#!/usr/bin/python 

from numpy import zeros
from array import array

import sys

import fakeCalc

def printHelp():
    print "testRun.py dataFile"

# Buffer to pass into method for scratch space
scratchBuf = zeros(10)

# Read in data to pass into method
if len(sys.argv) != 2:
    printHelp()
    exit()

dataFile = open(sys.argv[1], "r")

dataArr = array("I")

for dataPoint in dataFile:
    dataArr.append(int(dataPoint[0:-1]))

# Run calculations
fakeCalc.FakeCalc(dataArr, scratchBuf, 10, 10.5, 10, 10)

需要注意的几件事。我不能更改函数的参数,因为它是在多个代码库中使用的旧代码。缓冲区大小的缺乏,尽管显然不是理想的,但是可以在初始化硬件时解决,因为缓冲区是固定的。

该算法将calcSpace传入的缓冲区用作暂存空间,intermediateResults内部包含一些中间步骤的结果,并且dataBuffer只是原始数据,不会更改。

目前我正在     TypeError:在“ FakeCalc”方法中,类型为“ unsigned int”的参数1

所以问题简而言之: 可以在Python中分配这些缓冲区并传递给C吗?

预先感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

我找到了解决方法。

从python分配缓冲区并将其传递的一种简单方法是使用swig提供的“ carrays”。这是一个示例:

%module processBuffer

%include "stdint.i"
%include "carrays.i"

%array_class(uint32_t, buffer);

%{
    void processBuffer(unsigned int * buffer);
%}

void processBuffer(unsigned int * buffer);

在python中,创建缓冲区并以以下方式传递指针:

#!/usr/bin/python

import processBuffer

buffer = []

for x in range (0, 10):
    buffer.append(x)

print buffer

test = processBuffer.buffer(10);
for x in range (0, 10):
    test[x] = buffer[x]

processBuffer.processBuffer(test.cast())

到目前为止,这种方法没有问题。

对于那些感兴趣的人来说,看看生成的代码,原始问题就很清楚了。传入指针SWIG的假设是正在传递单个对象。为此,将创建一个临时对象以避免类型不兼容。这与数组分解。还有一些更复杂的解决方案也可以用于创建自定义类型映射,但是上述解决方案要简单得多。