【问题标题】:Use Swig to pass in a pointer to a buffer results in "TypeError"使用 Swig 传入指向缓冲区的指针会导致“TypeError”
【发布时间】:2019-06-19 15:55:41
【问题描述】:

我们有一个嵌入式系统,可以对数据缓冲区进行处理。当缓冲区被填满时,该处理由中断触发。希望是用模拟的输入数据测试算法。我们的数据科学团队使用 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?

提前感谢您的帮助!

【问题讨论】:

    标签: python c swig


    【解决方案1】:

    我找到了解决办法。

    从 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 会假设正在传递单个对象。为此,将创建一个临时对象以避免类型不兼容。这与数组有关。还有更复杂的解决方案也可以创建自定义类型映射,但上述解决方案要简单得多。

    【讨论】:

      猜你喜欢
      • 2021-01-13
      • 2015-04-15
      • 2013-07-26
      • 2020-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多