Обернуть список питонов в unsigned char * - PullRequest
4 голосов
/ 04 августа 2011

Редактировать: Привет всем !!

В настоящее время я пытаюсь получить доступ к функциям C ++ из Python и сталкиваюсь с проблемой, когда пытаюсь передать список Python в качестве аргумента функции.

вот определение функции C ++, к которому я пытаюсь получить доступ (используется для отправки команды на PC / SC-ридер):

SRpdu *SendAPDU(unsigned int uiAPDU, //Command
                unsigned int ucLE,   //Data expected for response
                unsigned int ucLC,   //Size of data buffer
                unsigned char * pucDataBuf = 0); //data buffer

Моя цель - вызвать эту функцию следующим образом из pythonкак в примере ниже.Цель состоит в том, чтобы преобразовать список [1,2,3] в неподписанный буфер char *:

SendAPDU(0x01020304, 0, 3, [1, 2, 3])

Записано в примере "33.9.1 Преобразование списка Python в символ **" из документации SWIG http://www.swig.org/Doc2.0/Python.html#Python_nn57, Я определил следующую карту типов для обработки unsigned char *, но, к сожалению, кажется, что карта типов не используется.На самом деле я могу использовать функцию только с последним аргументом, игнорируемым или установленным на Нет.

Код Python:

    >>> SendAPDU(0x02000000, 2, 0)  
    [36864, [30, 240]]                  #This call is working
    >>> SendAPDU(0x02000000, 2, 0, None)
    [36864, [30, 240]]                  #Also working

Затем, если я попытаюсь поместить список для данных команды (заменяя Нетв предыдущем примере), я получаю следующую ошибку:

>>> SendAPDU(0x02000000, 2, 4, [1, 2, 3, 4]) # HERE IT'S NOT WORKING
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "EMReaderEx.py", line 196, in SendAPDU
        def SendAPDU(self, *args): return _EMReaderEx.EMReaderEx_SendAPDU(self, *args)
    NotImplementedError: Wrong number or type of arguments for overloaded function 'EMReaderEx_SendAPDU'.
      Possible C/C++ prototypes are:
        EMReaderEx::SendAPDU(unsigned int,unsigned int,unsigned int,unsigned char *)
        EMReaderEx::SendAPDU(unsigned int,unsigned int,unsigned int)
        EMReaderEx::SendAPDU(SApdu &)

Я думаю, что мы здесь в случае «неправильного типа аргумента», поэтому я предполагаю, что карта типов не используется, потому что я думаю, но неУбедитесь, что функция не вызывается из-за несоответствия формата параметра.Таким образом, главный вопрос заключается в том, как я могу передать список и быть уверенным, что он будет принят функцией (и, следовательно, перехвачен картой типов)?

Я думаю, что что-то упустил, потому что я не нашел никакого рабочего решения для этого, и его следует относительно часто использовать.

Вот код кода карты типов в файле SWIG .i:

%typemap(in) unsigned char * {
      // Check if is a list 
      unsigned char *ucBuf = NULL;
      if (PyList_Check($input) && PyList_Size($input) > 0) {
        int size = PyList_Size($input);
        int i = 0;
        ucBuf = (unsigned char *) malloc((size+1)*sizeof(unsigned char));
        for (i = 0; i < size; i++) {
          PyObject *o = PyList_GetItem($input,i);
          if (PyLong_Check(o))
            ucBuf[i] = (unsigned char) PyLong_AsLong(o);
          else {
            PyErr_SetString(PyExc_TypeError,"list must contain integers");
            free(ucBuf);
            return NULL;
          }
        }
      } 
      $1 = &ucBuf[0];
    }

    %typemap(freearg) unsigned char * {
        if($1 != NULL)
            free( $1);
    }

В разделе Резюме, как сделать карту типов SWIG для вызова функции C ++:

SRpdu * SendAPDU(unsigned int uiAPDU, unsigned int ucLE, unsigned int ucLC, unsigned char * pucDataBuf);

Вот так из python:

SendAPDU(0x02000000, 2, 4, [1, 2, 3, 4])

Любая помощь приветствуется Заранее спасибо

ps Извините, если мой английский плохой, это не мой родной язык.

1 Ответ

1 голос
/ 08 августа 2011

Вы должны посмотреть на модульные массивы.

В частности, вы хотите позвонить fromlist. Если вы используете для передачи список вместо строки только потому, что вы думаете, что это то, что вам следует делать, доступна строковая функция, fromstring. В любом случае, вы можете просто инициализировать массив с помощью спецификатора формата 'B' (обратите внимание, что заглавная).

Пример использования:

array ('B', [1, 2, 1, 0, 3, 6, 0, 6])
...