使用 SWIG 创建 python2 和 python3 模块

Dee*_*shu 5 python swig python-2.7 python-3.x

我有一项任务,必须为现有的 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;
}
Run Code Online (Sandbox Code Playgroud)

我的界面文件是

/* 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);
Run Code Online (Sandbox Code Playgroud)

我的编译步骤

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
Run Code Online (Sandbox Code Playgroud)

在上面的编译格式模块中,在 python3 中工作正常,但在 python2 中失败,错误日志为

ImportError: ./_example.so: undefined symbol: PyUnicode_FromFormat
Run Code Online (Sandbox Code Playgroud)

如果我使用下面的编译命令

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
Run Code Online (Sandbox Code Playgroud)

模块正在使用 python2,但是当我尝试在 python3 中导入时,错误消息是

ImportError: /home/deepanshu/env/swig/env/src/deep/_example.so: undefined symbol: PyInstance_Type
Run Code Online (Sandbox Code Playgroud)

我确信错误是因为$(pkg-config --cflags --libs pythonX)我在 X 的位置指定了版本,但是如何确保我的模块适用于这两个 Python 版本?

我尝试了-py3swig 标志,但无法使模块适用于具有上述指定标志的两个 Python 版本。

Eri*_* L. 0

C 扩展在 python3 和 python2 中的工作方式不同。此链接可以帮助您确定需要在 C 级别执行哪些操作才能使该库同时适用于 python 2 和 3(不使用 swig)。http://python3porting.com/cextensions.html

使用 Swig,我要做的是利用点轮命名约定: https://packaging.python.org/tutorials/distributing-packages/#packaging-your-project

这样做,我将打包 python3 的库,并使包遵循wheel命名标准(“ https://www.python.org/dev/peps/pep-0425/#id1 ”“py3-none-any”)然后为Python2制作库并使用相同的策略(“py2-none-any”)打包它。然后你可以将它上传到Pypi,pip会知道它需要对python2使用py2,对python3使用py3。