1

I need to pass a pointer from Python to a C function. I'm currently trying with SWIG but I'm ready to switch to anything that will solve my issue :)

To simplify my problem, I wrote this empty C function in SWIG:

extern void myvoidp(void *p);

I've setup my .i and .c files, all compile fine and work in Python.

I'd like to pass a Numpy array. I can get the memory address of the Numpy data like this

>>> anp = array([1,2,3])
array([1, 2, 3])
>>> anp.ctypes.data
40546992

I can cast it to a void * like this with ctypes and numpy:

>>> anp.ctypes.data_as(ctypes.c_void_p)
c_void_p(40546992)

I've tried endless variants. Whatever I do, when I invoke my C function I get this error.

>>> myswig.myvoidp(anp.ctypes.data_as(ctypes.c_void_p))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: in method 'myvoidp', argument 1 of type 'void *'

I can't figure out how to write a Python / numpy statement that allows me to (simply) pass a pointer to my C function. :-(

  • Does `myswig.myvoidp(ctypes.c_void_p(40546992))` work? If not, then you can eliminate `numpy` from the question – Eric Aug 22 '18 at 08:09
  • Good idea. Yes, that yields the same error, so numpy is not playing in. I've found a way to make it work in ctypes though, I guess because in ctypes I specify that I want to pass a void pointer as the first arg. – Michael Seifert Aug 23 '18 at 11:08
  • So to be clear, it works using ctypes to call the function, but not swig? – Eric Aug 23 '18 at 16:36
  • Yes, that's correct. I believe that's because in ctypes I need to define the expected argument first. Which I do like this: self.clib_myvoidp.argtypes = [ctypes.c_void_p]. So somehow SWIG must mess up the definition of the void * type. – Michael Seifert Aug 24 '18 at 07:23
  • Hi, Is this possible without numpy.i ? Would like to convert any python object to a void pointer and vice versa. – Maverickgugu May 10 '23 at 09:12

1 Answers1

0

I guess you want to receive a pointer to the data of the NumPy array, so that you can access the array elements from C. NumPy ships with SWIG support which is easy and convenient to use. Just download numpy.i and place it in your project directory.

Just change the signature of the C function from (void *p) to (double *data, int length) and apply the NumPy typemap.

test.i

%module example
%{
#define SWIG_FILE_WITH_INIT
#include <stdio.h>

void myvoidp(double *data, int length) {
    printf("data = [ ");
    for (int i = 0; i < length; ++i) {
        printf("%f ", data[i]);
    }
    printf("]\n");
}
%}

%include "numpy.i"

%init %{
import_array();
%}

%apply (double* IN_ARRAY1, int DIM1) {(double *data, int length)}
void myvoidp(double *data, int length);

test.py

from example import myvoidp
from numpy import array

anp = array([1,2,3])
myvoidp(anp)

Example invocation:

$ swig -python test.i
$ clang -Wall -Wextra -Wpedantic -I /usr/include/python3.6m/ -fPIC -shared -o _example.so test_wrap.c -lpython3.6m
$ python3 test.py 
data = [ 1.000000 2.000000 3.000000 ]
Henri Menke
  • 10,705
  • 1
  • 24
  • 42