Creating a module for python2 and python3 using SWIG
I have a task where I have to write Python bindings for an existing C ++ library. Since SWIG supports not only Python but languages ββlike Java and Perl, I am using SWIG. I am relatively new to SWIG, so I have my doubts. I want my python library to be supported under Python 2.7 and Python 3.x. But I don't know how to do it. So if anyone can suggest me. Any help would be greatly appreciated. You can ask me for more details if you like.
What I have tried so far.
This is my code file.
/* example.c file */
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int my_mod(int n, int m) {
return n % m;
}
int sieve(int number) {
int* arr = malloc(sizeof (int) * (number + 10));
int* prime = malloc(sizeof (int) * (number + 10));
/* printf("Size of arr: %lu", sizeof(arr));
printf("Size of int: %lu", sizeof(int)); */
memset(arr, 0, sizeof(int) * (number + 10));
int counter = 0;
prime[counter++] = 2;
arr[0] = arr[1] = 0;
for (int i = 3; i * i <= number; i += 2) {
if (!arr[i]) {
for (int j = i + i; j < number; j += i) {
arr[j] = 1;
}
}
}
for (int i = 3; i < number; i += 2)
if (!arr[i])
prime[counter++] = i;
// free(arr);
// free(prime);
return counter;
}
And my interface file
/* example.i */
%module example
%{
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
extern int my_mod(int n, int m);
extern int sieve(int number);
%}
extern int my_mod(int n, int m);
extern int sieve(int number);
My steps to compile
swig -python example.i
gcc -fpic -c example.c example_wrap.c $(pkg-config --cflags --libs python3)
gcc -shared example.o example_wrap.o -o _example.so
The above compilation format unit works fine with python3 but fails in python2 with error log like
ImportError: ./_example.so: undefined symbol: PyUnicode_FromFormat
And if i use below compile command
swig -python example.i
gcc -fpic -c example.c example_wrap.c $(pkg-config --cflags --libs python2)
gcc -shared example.o example_wrap.o -o _example.so
Than the module works with python2, but when I try to import into python3 than the error message
ImportError: /home/deepanshu/env/swig/env/src/deep/_example.so: undefined symbol: PyInstance_Type
I'm pretty sure the error is because $(pkg-config --cflags --libs pythonX)
I am specifying the version in place of X, but how can I make sure my module works with Python versions?
I tried the -py3
swig flag , but I was unable to make the module work for both Python versions with the above flag.
source to share
C doesn't work the same in python3 vs python2. This link can help you figure out what you need to do at the C level in order for the library to work for both python 2 and 3 (not using swig). http://python3porting.com/cextensions.html
Using Swig, I would use the pip naming convention: https://packaging.python.org/tutorials/distributing-packages/#packaging-your-project
By doing this, I would package the library for python3 and make the package the following wheel naming standard (" https://www.python.org/dev/peps/pep-0425/#id1 " "py3 -none-any") and then create a library for Python2 and package it using the same strategy ("py2-none-any"). then you can upload it to Pypi and pip will know it needs to use py2 for python2 and py3 for python3.
source to share