I'm writing a Python C extension by SWIG but getting frustrated when passing binary buffer to C api functions. Here's my example:
In utils.c
#include "utils.h"
void my_print_hexbytes(uint32_t *bytes, uint32_t bytes_len)
{
uint32_t i;
for(i = 0; i < bytes_len; i++)
printf("%02x", bytes[i]);
printf("\n");
}
In utils.h
#include "commons.h"
#ifndef XXXX_UTILS_H
#define XXXX_UTILS_H
void my_print_hexbytes(uint32_t *bytes, uint32_t bytes_len);
#endif /* XXXX_UTILS_H */
In commons.h
#ifndef XXXX_COMMONS_H
#define XXXX_COMMONS_H
....
....
#include <stdint.h>
....
....
#endif
In xxxx_for_py.i
%module xxxx_for_py
%{
#define SWIG_FILE_WITH_INIT
#include "commons.h"
#include "utils.h"
%}
%include "stdint.i"
void my_print_hexbytes(uint32_t *bytes, uint32_t bytes_len);
1st Try
After compiling out _xxxx_for_py.so
, I gave a try testing it in IPython:
In [1]: import xxxx_for_py
In [2]: from ctypes import *
In [3]: a_t = c_uint * 2
In [4]: a = a_t(0x1, 0x2)
In [5]: xxxx_for_py.my_print_hexbytes(a, 2)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-5-3c023fcf8b04> in <module>()
----> 1 xxxx_for_py.my_print_hexbytes(a, 2)
TypeError: in method 'my_print_hexbytes', argument 1 of type 'uint32_t *'
That time I had no idea how to handle this case. I tried changing the a
as bytearray
but it didn't work.
Not sure if anyone who could help me on this issue. Thanks!
2nd Try
Thanks for @Petesh comment. I've hit a try by casting a
to POINTER(c_uint)
but still not work :(
In [5]: xxxx_for_py.my_print_hexbytes(cast(a, POINTER(c_uint)), 2)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-5-2abb9dae484d> in <module>()
----> 1 xxxx_for_py.my_print_hexbytes(cast(a, POINTER(c_uint)), 2)
TypeError: in method 'my_print_hexbytes', argument 1 of type 'uint32_t *'
3rd Try
Referenced by Unbounded Array section in SWIG documentation, I added carray.i
to xxxx_for_py.i
In xxxx_for_py.i
....
....stdint.i"
%include "carrays.i"
%array_class(uint32_t, uint32Array)
....
After re-compiling and loading .so
, it still got same error
In [1]: import xxxx_for_py
In [2]: a = xxxx_for_py.uint32Array(2)
In [3]: a[0] = 0x0
In [4]: a[1] = 0x1
In [5]: xxxx_for_py.my_print_hexbytes(a, 2)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-5-3c023fcf8b04> in <module>()
----> 1 xxxx_for_py.my_print_hexbytes(a, 2)
TypeError: in method 'my_print_hexbytes', argument 1 of type 'uint32_t *'
4th Try
After a week later at that time, user Nethanel post an answer. Though it still did not work, it could help me find something interesting.