I'm trying to use SWIG to wrap an existing C library for use in Python. I'm running swig 2.0.10 on Windows XP with Python 2.7.4. The problem I'm encountering is that I'm unable to call a wrapped C function that has a pointer to an int as an argument which is where the function result is to be stored. I've distilled the problem into the follow example code:
The C function in convert.c:
#include <stdio.h>
#include "convert.h"
#include <stdlib.h>
int convert(char *s, int *i)
{
*i = atoi(s);
return 0;
}
The header file in convert.h
#ifndef _convert_h_
#define _convert_h_
int convert(char *, int *);
#endif
The swig interface file in convert.i
/* File : convert.i */
%module convert
%{
#include "convert.h"
%}
%include "convert.h"
All of this is being built into a .pyd file using Visual C++ 2010. When the build is complete, I'm left with two files: convert.py and _convert.pyd in the build directory. I open a command window in this directory and start python session and enter the following:
Python 2.7.4 (default, Apr 6 2013, 19:54:46) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from ctypes import *
>>> import convert
>>> dir(convert)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', '_convert', '_newclass', '_object', '_swig_getattr', '_swig_property', '_swig_repr', '_swig_setattr', '_swig_setattr_nondynamic', 'convert']
>>> i = c_int()
>>> i
c_long(0)
>>> convert.convert('1234', byref(i))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: in method 'convert', argument 2 of type 'int *'
Why is my pointer object being rejected? What should I do to make this work?
SWIG
and ctypes
are different libraries, so you can't pass ctypes objects directly to SWIG-wrapped functions.
In SWIG, the %apply
command can apply typemaps to common parameter types to configure them as INPUT
, INOUT
, or OUTPUT
parameters. Try the following:
%module convert
%{
#include "convert.h"
%}
%apply int *OUTPUT {int*};
%include "convert.h"
Python will no longer require the parameter on input, and will change the output of the function to be a tuple of the return value and any INOUT
or OUTPUT
parameters:
>>> import convert
>>> convert.convert('123')
[0, 123]
Note that parameters beyond the POD (plain old data) types usually require writing your own typemaps. Consult the SWIG Documentation for more details.