简体   繁体   English

使用Cython传递int和struct包装C代码的最小示例

[英]Minimal example of wrapping C code with Cython- passing int and struct

The code that I show below works, but I am not exactly sure why . 我在下面展示的代码有效, 但我不确定为什么

I am using: 我在用:

  • Mac OSX 10.8.5 Mac OSX 10.8.5
  • brewed Python 2.7.5 酿造Python 2.7.5
  • Cython 0.20.2 Cython 0.20.2

This code is taken primarily from this video tutorial and git page , but unfortunately did not work for me 'out of the box'. 这段代码主要来自这个视频教程git页面 ,但遗憾的是我没有“开箱即用”。

The goal of this wrapping to provide access through Python to a trivial C function, which accepts either integers or a structure of integers and adds them together. 这种包装的目的是通过Python提供对一个简单的C函数的访问,该函数接受整数或整数结构并将它们加在一起。

There are 5 files needed for this, described below: 这需要5个文件,如下所述:

  • adder.c : C code of the two adder functions: add (scalar inputs) and pair_add (struct inputs) adder.c :两个加法器函数的C代码: add (标量输入)和pair_add (struct输入)
  • adder.h : header file for adder.c adder.hadder.h头文件
  • c_adder.pxd : a cython header file- essentially tells cython which parts of the main header file to pay attention to c_adder.pxd :一个cython头文件 - 本质上告诉cython主头文件的哪些部分需要注意
  • cy_adder.pyx : the cython code used to define both functions in the python namespace cy_adder.pyx :用于在python命名空间中定义两个函数的cython代码
  • setup.py : a distutils file which performs the compiling of the cython code setup.py :一个distutils文件,用于执行cython代码的编译

and the process produces two files 并且该过程生成两个文件

  • c_adder.c : an intermediate cython c file c_adder.c :一个中级cython c文件
  • c_adder.so : the python module which can be imported into a namespace c_adder.so :可以导入命名空间的python模块

The input files are below: 输入文件如下:

adder.c adder.c

#include <stdlib.h>
#include "adder.h"

int
pair_add(PAIR * ppair) {
    return ppair->x + ppair->y;
}

int
add(int x, int y) {
    return x + y;
}

adder.h adder.h

typedef struct {
    int x;
    int y;
} PAIR;

int pair_add(PAIR * ppair);
int add(int, int);

c_adder.pxd c_adder.pxd

cdef extern from "adder.h":

    ctypedef struct PAIR:
        int x
        int y


    int add(int x, int y)
    int pair_add(PAIR * ppair)

cy_adder.pyx cy_adder.pyx

cimport c_adder

def add(x, y):
    return c_adder.add(x, y)

def pair_add(x, y):
    cdef c_adder.PAIR pair
    pair.x = x
    pair.y = y
    return c_adder.pair_add(&pair)

setup.py setup.py

from setuptools import setup
from setuptools.extension import Extension
from Cython.Distutils import build_ext
from Cython.Build import cythonize


ext_modules = cythonize([Extension("cy_adder", ["cy_adder.pyx",'adder.c'])])


setup(
  name = 'Hello world app',
  cmdclass = {'build_ext': build_ext},
  ext_modules = ext_modules
)

I was able to successfully create a .so file by running 我能够通过运行成功创建.so文件

$ python setup.py build_ext --inplace

In the same directory as the above files. 在与上述文件相同的目录中。 It is then possible to load cy_adder into the namespace of a python interpreter. 然后可以将cy_adder加载到python解释器的命名空间中。


The question 这个问题

In the setup declaration, I have included adder.c as an auxiliary module. 在设置声明中,我将adder.c作为辅助模块包含在内。

If I don't do this I get the following error when I import the .so file: 如果我不这样做 ,我导入.so文件时会出现以下错误:

ImportError: dlopen(./cy_adder.so, 2): Symbol not found: _add
  Referenced from: ./cy_adder.so
  Expected in: flat namespace
 in ./cy_adder.so

Is there a step that I am missing which would mean that I don't need to explicitly pass adder.c along with my setup command? 是否有一个我遗漏的步骤意味着我不需要显式传递adder.c和我的setup命令? Am I opening myself up to some potential instability by doing this? 通过这样做,我是否打开了自己的潜在不稳定性?

The adder.c file needs to be referenced somewhere so it knows where to find the implementation of add . 需要在某处引用adder.c文件,以便知道在哪里可以找到add的实现。 As you discovered, listing adder.c as an additional source file works. 如您adder.c ,将adder.c列为附加源文件。 A more common way to use external (shared) C libraries is to compile it as libadder.so and link it via the libraries parameter in your Extension declaration. 使用外部(共享)C库的一种更常见的方法是将其编译为libadder.so,并通过Extension声明中的libraries参数链接它。

For something this simple you could also just write 对于这个简单的东西你也可以写

cdef extern from "adder.c":   # note the .c
    int add(int x, int y)
    ...

or put the entire implementation in the .h file. 或者将整个实现放在.h文件中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM