Mac上使用SWIG来在Python里调用C的踩坑记录

Mac上SWIG踩坑记录

安装

可以通过brew/anaconda/下载源码自行编译等方式;这个教程里有针对各个平台的详细安装步骤.
Mac运行brew install swig即可

例子

偷懒,直接用的官方文档的例子

  1. 假设需要调用的C语言代码为:
 /* File : example.c */
 
 #include 
 double My_variable = 3.0;
 
 int fact(int n) {
     if (n <= 1) return 1;
     else return n*fact(n-1);
 }
 
 int my_mod(int x, int y) {
     return (x%y);
 }
 	
 char *get_time()
 {
     time_t ltime;
     time(&ltime);
     return ctime(&ltime);
 }
  1. 接下来,写一个SWIG可以识别的接口文件:
 /* example.i */
 %module example
 %{
 /* Put header files here or function declarations like below */
 extern double My_variable;
 extern int fact(int n);
 extern int my_mod(int x, int y);
 extern char *get_time();
 %}
 
 extern double My_variable;
 extern int fact(int n);
 extern int my_mod(int x, int y);
 extern char *get_time();
  1. 构建Python模块
    Unix系统下输入:
swig -python example.i
gcc -c example.c example_wrap.c \
        -I/usr/local/include/python2.7
ld -shared example.o example_wrap.o -o _example.so 
  1. 第3步的替代方案
    在Mac下编译的时候因为Python环境等问题容易导致找不到一些要引用的头文件,而且命令输入很麻烦,这里我参照这个回答c - Python.h not found using swig and Anaconda Python - Stack Overflow 使用distutils来进行生成.

首先编写一个setup.py文件,例子如下:

    # setup.py
    
    from distutils.core import setup, Extension
    
    
    example_module = Extension('_example', sources=['example_wrap.c', 'example.c'])
    
    setup(name='example', ext_modules=[example_module], py_modules=["example"])

然后使用命令python setup.py build_ext --inplace编译即可.之后就可以愉快地import example了!

Over.

一些博客或资源

  1. 利用 SWIG 对 C++ 库进行 Python 包装 - 个人文章 - SegmentFault 思否 一个不错的例子(有点像翻译的官方文档233),不过SWIG只支持了C++的一个子集
  2. 用SWIG向Python提供C++里STL的容器 · 零壹軒·笔记
  3. 使用SWIG实现Python调用C/C++代码 | 白码羊堂 这个主要针对C,例子比较细致,整个流程很清晰
  4. SWIG之为C/C++的API生成Python调用接口基础 | WalkerTalking一个非常详细的例子,对SWIG的原理也进行了解释,作者对C++和SWIG的结合进行了很多尝试,可以参考.
  5. c - Python.h not found using swig and Anaconda Python - Stack Overflow 详细介绍了Mac上使用SWIG的相关命令, 这个答主是天使!
  6. SWIG设置编译选项 python - How may I override the compiler (gcc) flags that setup.py uses by default? - Stack Overflow 如果要用gcc而不是clang的话 在终端里先输入CC=gcc-8

你可能感兴趣的:(炼丹玄学,编译原理)