使用 SWIG 为 python2 和 python3 创建一个模块
Posted
技术标签:
【中文标题】使用 SWIG 为 python2 和 python3 创建一个模块【英文标题】:Creating a module for python2 and python3 with SWIG 【发布时间】:2017-05-10 11:30:05 【问题描述】:我有一个任务,我必须为现有的 C++ 库编写 Python 绑定。由于 SWIG 不仅支持 Python,还支持 Java 和 Perl 等语言,所以我使用的是 SWIG。我在 SWIG 中相对较新,所以我有疑问。我希望我的 python 库在 Python 2.7 和 Python 3.x 下是可支持的。但我不知道如何做到这一点。所以如果有人可以建议我。任何帮助,将不胜感激。如果您愿意,可以向我询问更多详细信息。
到目前为止我已经尝试过什么。
这是我的代码文件。
/* 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;
而我的接口文件是
/* 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);
我的编译步骤
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
在上述编译格式中,模块在 python3 中工作正常,但在 python2 中失败,错误日志为
ImportError: ./_example.so: undefined symbol: PyUnicode_FromFormat
如果我使用下面的编译命令
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
模块正在使用 python2,但是当我尝试在 python3 中导入时,错误消息是
ImportError: /home/deepanshu/env/swig/env/src/deep/_example.so: undefined symbol: PyInstance_Type
我确定错误是因为$(pkg-config --cflags --libs pythonX)
我在 X 的位置指定版本,但我如何确保我的模块适用于两个 Python 版本?
我尝试了 swig 的 -py3
标志,但我无法使模块适用于具有上述指定标志的两个 Python 版本。
【问题讨论】:
您不能同时链接到 Python 2.7 和 Python 3.x。如果要同时支持这两个版本,则需要在生成的 Python 文件中执行并在 Python 版本上引入分支。 【参考方案1】:C 扩展在 python3 和 python2 中的工作方式不同。此链接可以帮助您确定在 C 级别上需要做什么才能使库同时适用于 python 2 和 3(不使用 swig)。 http://python3porting.com/cextensions.html
使用 Swig,我要做的是使用 pip ***命名约定: https://packaging.python.org/tutorials/distributing-packages/#packaging-your-project
这样做,我会为 python3 打包库并使包遵循轮命名标准(“https://www.python.org/dev/peps/pep-0425/#id1”“py3-none-any”),然后为 Python2 制作库并使用相同的策略打包它(“py2-none-any”)。然后你可以将它上传到 Pypi,pip 就会知道它需要将 py2 用于 python2,将 py3 用于 python3。
【讨论】:
以上是关于使用 SWIG 为 python2 和 python3 创建一个模块的主要内容,如果未能解决你的问题,请参考以下文章
在 Mac 上的 Python 2.7.3 中导入 .pyd(使用 SWIG 创建)