通过在Cython中编译C代码来扩展Python

时间:2015-03-27 04:21:36

标签: cython

我在从R软件包(fastclime)编译C中的特定源文件时遇到问题,因此我可以将其用作Python模块。这是我在线提取R包的代码:

from __future__ import division
import os
import sys
import glob

if not os.path.exists('fastlp.h'):
    ! wget http://cran.r-project.org/src/contrib/fastclime_1.2.4.tar.gz
    ! tar -xzvf fastclime_1.2.4.tar.gz

在R包中(在[src]文件夹中)是源文件[parametric.c]。我想在Python中将其编译为具有numpy输入的模块。由于我无法立即测试此代码的功能,我首先尝试编译[fastlp.c]源文件。使用fastlp,我可以创建一个玩具示例来测试我是否在Python中成功编译了fastlp版本。然后我可以扩展编译[parametric.c]

的步骤

这是我的尝试:

1)首先我创建头文件,因为它不存在

 %%file fastclime/src/fastlp.h

 int ratio_test0(double *dy, int *idy,int ndy, double *y, double *ybar, double mu);
 void fastlp(double *obj, double *mat, double *rhs, int *m0 , int *n0, double *opt, int *status, double *lam)
 void solver20(int m,int n,int nz,int *ia, int *ka, double *a,double *b, double *c)
 int ratio_test0(double *dy, int *idy,int ndy,double *y, double *ybar, double mu)

2)接下来,我在Cython中编写用于包装C代码的文件:

 %%file fastlp.pxd

 cdef extern from "fastclime/src/fastlp.h":
 void fastlp(double *obj, double *mat, double *rhs, int *m0 , int *n0, double *opt, int *status, double *lam)

 %%file fastlp.pyx

 cimport fastlp

 def fastlp(double *obj, double *mat, double *rhs, int *m0 , int *n0, double *opt, int *status, double *lam):
 fastlp.fastlp(*obj, *mat, *rhs, *m0, *n0, *opt, *status, *lam)

3)接下来我使用distutils构建系统进行编译。

 %%file setup.py

 from distutils.core import setup, Extension
 from Cython.Build import cythonize

 ext = Extension("fastlp",
            sources=["fastlp.pyx", "fastclime/src/fastlp.c"])

 setup(name="fastlp",
       ext_modules = cythonize([ext]))

4)最后我编译

 ! python setup.py build_ext -i  

#4是事情失败的地方。不确定如何在步骤1-3中解决它。

5)如果一切都成功(它不是),我应该可以运行这段代码(取自小插图)

 import fastlp as flp
 import numpy as np

 A=np.array([-1.0,-1,0,1,-2,1]).reshape((3,2))
 b=np.array([-1.0,-2,1])
 c=np.array([-2.0,3])


 flp.fastlp(c,A,b)

这应该输出矢量[2.,1。]。

我对Cython或Python不太熟悉,但获得此功能对未来的项目有很大帮助。有人可以让我知道在C中获取源文件的正确方法,并完成与numpy接口创建Python模块的步骤吗?

谢谢!

更新:

我试图关注此网站上的Numpy + Cython示例:https://scipy-lectures.github.io/advanced/interfacing_with_c/interfacing_with_c.html

我已经更新了我的代码

%%cython
# import both numpy and the Cython declarations for numpy
import numpy as np
cimport numpy as np

# if you want to use the Numpy-C-API from Cython
# (not strictly necessary for this example)
np.import_array()

# cdefine the signature of our c function
cdef extern from "/home/bitnami/STA663-pura-project/fastclime/src/fastlp.h":
    void fastlp(double *obj, double *mat, double *rhs, int *m0 , int *n0, double *opt, int *status, double *lam)

# create the wrapper code, with numpy type annotations
def fastlp_func(np.ndarray[double, ndim=1, mode="c"] obj not None,
            np.ndarray[double, ndim=2, mode="c"] mat not None,
            np.ndarray[double, ndim=1, mode="c"] rhs not None,
            double lam):
    cdef int m1 = mat.shape[0]
    cdef int m2 = mat.shape[1]
    cdef np.ndarray[double, ndim=1, mode='c'] z = np.zeros(obj.shape[0])
    cdef double [:] zp = z #convert from Python to C object
    cdef int stat = 0
    cdef double lambd = 0
    fastlp(<double*> np.PyArray_DATA(obj),
            <double*> np.PyArray_DATA(mat.T),
            <double*> np.PyArray_DATA(rhs),
            &m1,
            &m2,
            &zp[0],  
            &stat, 
            &lambd  
       )

但是,我收到以下错误(我根本不理解):

---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
<ipython-input-85-29981393af41> in <module>()
----> 1 get_ipython().run_cell_magic(u'cython', u'', u'# import both numpy and the Cython declarations for numpy\nimport numpy as np\ncimport numpy as np\n\n# if you want to use the Numpy-C-API from Cython\n# (not strictly necessary for this example)\nnp.import_array()\n\n# cdefine the signature of our c function\ncdef extern from "/home/bitnami/STA663-pura-project/fastclime/src/fastlp.h":\n    void fastlp(double *obj, double *mat, double *rhs, int *m0 , int *n0, double *opt, int *status, double *lam)\n    \n# create the wrapper code, with numpy type annotations\ndef fastlp_func(np.ndarray[double, ndim=1, mode="c"] obj not None,\n                np.ndarray[double, ndim=2, mode="c"] mat not None,\n                np.ndarray[double, ndim=1, mode="c"] rhs not None,\n                double lam):\n    cdef int m1 = mat.shape[0]\n    cdef int m2 = mat.shape[1]\n    cdef np.ndarray[double, ndim=1, mode=\'c\'] z = np.zeros(obj.shape[0])\n    cdef double [:] zp = z #convert from Python to C object\n    cdef int stat = 0\n    cdef double lambd = 0\n    fastlp(<double*> np.PyArray_DATA(obj),\n                <double*> np.PyArray_DATA(mat.T),\n                <double*> np.PyArray_DATA(rhs),\n                &m1,\n                &m2,\n                &zp[0],  \n                &stat, \n                &lambd  \n           )')

/home/bitnami/anaconda/lib/python2.7/site-packages/IPython/core/interactiveshell.pyc in run_cell_magic(self, magic_name, line, cell)
   2160             magic_arg_s = self.var_expand(line, stack_depth)
   2161             with self.builtin_trap:
-> 2162                 result = fn(magic_arg_s, cell)
   2163             return result
   2164 

/home/bitnami/anaconda/lib/python2.7/site-packages/IPython/extensions/cythonmagic.pyc in cython(self, line, cell)

/home/bitnami/anaconda/lib/python2.7/site-packages/IPython/core/magic.pyc in <lambda>(f, *a, **k)
    191     # but it's overkill for just that one bit of state.
    192     def magic_deco(arg):
--> 193         call = lambda f, *a, **k: f(*a, **k)
    194 
    195         if callable(arg):

/home/bitnami/anaconda/lib/python2.7/site-packages/IPython/extensions/cythonmagic.pyc in cython(self, line, cell)
    269             self._code_cache[key] = module_name
    270 
--> 271         module = imp.load_dynamic(module_name, module_path)
    272         self._import_all(module)
    273 

ImportError: /home/bitnami/.cache/ipython/cython/_cython_magic_16feaf686ed172960f59fa6333ae74b5.so: undefined symbol: fastlp

0 个答案:

没有答案