开发者

Wrap python list to unsigned char*

开发者 https://www.devze.com 2023-03-26 02:21 出处:网络
Edit : Hi all !! I\'m currently trying to access to C++ functions from Python and I\'m facing to a problem when I try to pass Python list as argument to a function.

Edit : Hi all !!

I'm currently trying to access to C++ functions from Python and I'm facing to a problem when I try to pass Python list as argument to a function.

here is the C++ function definition I'm trying to access (used to send command to PC/SC reader) :

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

My goal is to call this function as following from python like in example below. The goal is to convert the list [1,2,3] to a unsigned char * buffer :

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

Insipired from example "33.9.1 Converting Python list to a char **" from SWIG documentation http://www.swig.org/Doc2.0/Python.html#Python_nn57, I defined following typemap to handle unsigned char * but unfortunately it seems tha开发者_高级运维t the typemap is not used. Actually I can use the function only with last argument ignored or set to None.

Python code :

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

Then if I try to put a list for data of the command (replacing None in previous example), I receive the following error :

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

I think we are here in case of "Wrong type of argument", so I guess that the typemap is not used because I think, but not sure, that the function is not called because of the parameter format doesn't match. So the main question is how can I pass a list and be sure that will be accepted by the function (and therefore catched by the typemap) ?

I think I missed something because I didn't found any working solution for that, and it should relatively used often.

Here is the code of the typemap code in SWIG .i file:

%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);
    }

In Resume, how to do the SWIG typemap to call C++ function :

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

Like that from python:

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

Any help is welcome Thanks in advance

p.s. Sorry if my english is bad, it's not my native language.


You should look into module arrays.

In particular, you are looking to call fromlist. If you are using a list to pass instead of a string just because you think that's what you should do, there is a string function available, fromstring. Either way, you can simply initialize the array with format specifier 'B' (notice that capital).

Example usage:

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

精彩评论

暂无评论...
验证码 换一张
取 消