Использование Swig для передачи указателя на буфер приводит к «TypeError» - PullRequest
0 голосов
/ 25 января 2019

У нас есть встроенная система, которая выполняет обработку буфера данных. Обработка запускается прерыванием, когда буфер заполнен. Желание состоит в том, чтобы протестировать алгоритм с имитацией входных данных. Наша команда по обработке данных использует 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, используется алгоритмом как промежуточное пространство, промежуточные результаты содержат внутренние результаты некоторых промежуточных шагов, а dataBuffer - просто необработанные данные и не изменяется.

В настоящее время я получаю Ошибка типа: в методе 'FakeCalc', аргумент 1 типа 'unsigned int'

Итак, вопрос в двух словах: Можно ли выделить эти буферы в Python и перейти в C?

Заранее спасибо за помощь!

1 Ответ

0 голосов
/ 03 февраля 2019

Я нашел решение.

Простой способ выделить буфер из python и передать его - это использовать 'carrays', предоставленные swig. Вот пример:

%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 предполагает, что передается один объект. Для этого создается временный объект, чтобы избежать несовместимости типов. Это ломается с массивами. Существуют более сложные решения, которые также работают при создании пользовательских типов карт, но приведенное выше решение намного проще.

...