使用 cython 简单包装 C 代码

2024-02-27

我有许多 C 函数,我想从 python 调用它们。 cython 似乎是可行的方法,但我无法真正找到具体如何完成此操作的示例。我的 C 函数如下所示:

void calculate_daily ( char *db_name, int grid_id, int year,
                       double *dtmp, double *dtmn, double *dtmx, 
                       double *dprec, double *ddtr, double *dayl, 
                       double *dpet, double *dpar ) ;

我想做的就是指定前三个参数(一个字符串和两个整数),并恢复 8 个 numpy 数组(或 python 列表。所有双精度数组都有 N 个元素)。我的代码假设指针指向已经分配的内存块。此外,生成的 C 代码应该链接到一些外部库。


这是传递 numpy 数组的一个微小但完整的示例 逻辑上到外部 C 函数

fc( int N, double* a, double* b, double* z )  # z = a + b

使用 Cython。 (这对于熟悉这一点的人来说肯定是众所周知的。 欢迎评论。 最后更改:2011 年 2 月 23 日,Cython 0.14。)

首先阅读或浏览Cython 构建 http://docs.cython.org/src/quickstart/build.html and Cython 与 NumPy http://docs.cython.org/src/tutorial/numpy.html .

2 steps:

  • python f-setup.py build_ext --inplace
    turns f.pyx and fc.cpp -> f.so,一个动态库
  • python test-f.py
    import f loads f.so; f.fpy( ... )呼叫 Cfc( ... ).

python f-setup.py uses distutils运行 cython、编译并链接:
cython f.pyx -> f.cpp
编译f.cpp and fc.cpp
link f.o fc.o -> f.so, python 的动态库import f将加载。

对于学生,我建议:画出这些步骤的图表, 查看下面的文件,然后下载并运行它们。

(distutils是一个巨大而复杂的包,用于 制作用于分发的 Python 包并安装它们。 这里我们只使用其中的一小部分来编译和链接到f.so。 这一步与 Cython 无关,但可能会令人困惑; .pyx 中的简单错误可能会导致 g++ 编译和链接出现大量晦涩的错误消息。 也可以看看distutils 文档 http://docs.python.org/distutils and/or 关于 distutils 的 SO 问题 https://stackoverflow.com/questions/tagged/distutils+python .)

Like make, setup.py将重新运行cython f.pyx and g++ -c ... f.cpp if f.pyxf.cpp.
为了清理,rm -r build/ .

替代方案setup.py将在脚本或 Makefile 中单独运行这些步骤:
cython --cplus f.pyx -> f.cpp # see cython -h
g++ -c ... f.cpp -> f.o
g++ -c ... fc.cpp -> fc.o
cc-lib f.o fc.o -> dynamic library f.so.
修改cc-lib-mac包装纸 下面是您的平台和安装:它不漂亮,但是很小。

对于 Cython 包装 C 的真实示例, 查看几乎任何文件中的 .pyx 文件SciKit http://scikits.appspot.com/scikits .

也可以看看:适用于 NumPy 用户的 Cython http://docs.cython.org/src/userguide/numpy_tutorial.html and 所以问题/标记/cython https://stackoverflow.com/questions/tagged/cython .


要解压以下文件, 比如说,将批次剪切粘贴到一个大文件中cython-numpy-c-demo, 然后在 Unix 中(在一个干净的新目录中)运行sh cython-numpy-c-demo.

#--------------------------------------------------------------------------------
cat >f.pyx <<\!
# f.pyx: numpy arrays -> extern from "fc.h"
# 3 steps:
# cython f.pyx  -> f.c
# link: python f-setup.py build_ext --inplace  -> f.so, a dynamic library
# py test-f.py: import f gets f.so, f.fpy below calls fc()

import numpy as np
cimport numpy as np

cdef extern from "fc.h": 
    int fc( int N, double* a, double* b, double* z )  # z = a + b

def fpy( N,
    np.ndarray[np.double_t,ndim=1] A,
    np.ndarray[np.double_t,ndim=1] B,
    np.ndarray[np.double_t,ndim=1] Z ):
    """ wrap np arrays to fc( a.data ... ) """
    assert N <= len(A) == len(B) == len(Z)
    fcret = fc( N, <double*> A.data, <double*> B.data, <double*> Z.data )
        # fcret = fc( N, A.data, B.data, Z.data )  grr char*
    return fcret

!

#--------------------------------------------------------------------------------
cat >fc.h <<\!
// fc.h: numpy arrays from cython , double*

int fc( int N, const double a[], const double b[], double z[] );
!

#--------------------------------------------------------------------------------
cat >fc.cpp <<\!
// fc.cpp: z = a + b, numpy arrays from cython

#include "fc.h"
#include <stdio.h>

int fc( int N, const double a[], const double b[], double z[] )
{
    printf( "fc: N=%d a[0]=%f b[0]=%f \n", N, a[0], b[0] );
    for( int j = 0;  j < N;  j ++ ){
        z[j] = a[j] + b[j];
    }
    return N;
}
!

#--------------------------------------------------------------------------------
cat >f-setup.py <<\!
# python f-setup.py build_ext --inplace
#   cython f.pyx -> f.cpp
#   g++ -c f.cpp -> f.o
#   g++ -c fc.cpp -> fc.o
#   link f.o fc.o -> f.so

# distutils uses the Makefile distutils.sysconfig.get_makefile_filename()
# for compiling and linking: a sea of options.

# http://docs.python.org/distutils/introduction.html
# http://docs.python.org/distutils/apiref.html  20 pages ...
# https://stackoverflow.com/questions/tagged/distutils+python

import numpy
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
# from Cython.Build import cythonize

ext_modules = [Extension(
    name="f",
    sources=["f.pyx", "fc.cpp"],
        # extra_objects=["fc.o"],  # if you compile fc.cpp separately
    include_dirs = [numpy.get_include()],  # .../site-packages/numpy/core/include
    language="c++",
        # libraries=
        # extra_compile_args = "...".split(),
        # extra_link_args = "...".split()
    )]

setup(
    name = 'f',
    cmdclass = {'build_ext': build_ext},
    ext_modules = ext_modules,
        # ext_modules = cythonize(ext_modules)  ? not in 0.14.1
    # version=
    # description=
    # author=
    # author_email=
    )

# test: import f
!

#--------------------------------------------------------------------------------
cat >test-f.py <<\!
#!/usr/bin/env python
# test-f.py

import numpy as np
import f  # loads f.so from cc-lib: f.pyx -> f.c + fc.o -> f.so

N = 3
a = np.arange( N, dtype=np.float64 )
b = np.arange( N, dtype=np.float64 )
z = np.ones( N, dtype=np.float64 ) * np.NaN

fret = f.fpy( N, a, b, z )
print "fpy -> fc z:", z

!

#--------------------------------------------------------------------------------
cat >cc-lib-mac <<\!
#!/bin/sh
me=${0##*/}
case $1 in
"" )
    set --  f.cpp fc.cpp ;;  # default: g++ these
-h* | --h* )
    echo "
$me [g++ flags] xx.c yy.cpp zz.o ...
    compiles .c .cpp .o files to a dynamic lib xx.so
"
    exit 1
esac

# Logically this is simple, compile and link,
# but platform-dependent, layers upon layers, gloom, doom

base=${1%.c*}
base=${base%.o}
set -x

g++ -dynamic -arch ppc \
    -bundle -undefined dynamic_lookup \
    -fno-strict-aliasing -fPIC -fno-common -DNDEBUG `# -g` -fwrapv \
    -isysroot /Developer/SDKs/MacOSX10.4u.sdk \
    -I/Library/Frameworks/Python.framework/Versions/2.6/include/python2.6 \
    -I${Pysite?}/numpy/core/include \
    -O2 -Wall \
    "$@" \
    -o $base.so

# undefs: nm -gpv $base.so | egrep '^ *U _+[^P]'
!

# 23 Feb 2011 13:38
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 cython 简单包装 C 代码 的相关文章

  • Python 中的 Lanczos 插值与 2D 图像

    我尝试重新缩放 2D 图像 灰度 图像大小为 256x256 所需输出为 224x224 像素值范围从 0 到 1300 我尝试了两种使用 Lanczos 插值来重新调整它们的方法 首先使用PIL图像 import numpy as np
  • Python 的键盘中断不会中止 Rust 函数 (PyO3)

    我有一个使用 PyO3 用 Rust 编写的 Python 库 它涉及一些昂贵的计算 单个函数调用最多需要 10 分钟 从 Python 调用时如何中止执行 Ctrl C 好像只有执行结束后才会处理 所以本质上没什么用 最小可重现示例 Ca
  • Django 管理员在模型编辑时间歇性返回 404

    我们使用 Django Admin 来维护导出到我们的一些站点的一些数据 有时 当单击标准更改列表视图来获取模型编辑表单而不是路由到正确的页面时 我们会得到 Django 404 页面 模板 它是偶尔发生的 我们可以通过重新加载三次来重现它
  • 为 Anaconda Python 安装 psycopg2

    我有 Anaconda Python 3 4 但是每当我运行旧代码时 我都会通过输入 source activate python2 切换到 Anaconda Python 2 7 我的问题是我为 Anaconda Python 3 4 安
  • SQLALchemy .query:类“Car”的未解析属性引用“query”

    我有一个这里已经提到的问题https youtrack jetbrains com issue PY 44557 https youtrack jetbrains com issue PY 44557 但我还没有找到解决方案 我使用 Pyt
  • Spark KMeans 无法处理大数据吗?

    KMeans 有几个参数training http spark apache org docs latest api python pyspark mllib html highlight kmeans pyspark mllib clus
  • 如何使用 OpencV 从 Firebase 读取图像?

    有没有使用 OpenCV 从 Firebase 读取图像的想法 或者我必须先下载图片 然后从本地文件夹执行 cv imread 功能 有什么办法我可以使用cv imread link of picture from firebase 您可以
  • 绘制方程

    我正在尝试创建一个函数 它将绘制我告诉它的任何公式 import numpy as np import matplotlib pyplot as plt def graph formula x range x np array x rang
  • 添加不同形状的 numpy 数组

    我想添加两个不同形状的 numpy 数组 但不进行广播 而是将 缺失 值视为零 可能最简单的例子是 1 2 3 2 gt 3 2 3 or 1 2 3 2 1 gt 3 2 3 1 0 0 我事先不知道形状 我正在弄乱每个 np shape
  • Flask如何获取请求的HTTP_ORIGIN

    我想用我自己设置的 Access Control Allow Origin 标头做出响应 而弄清楚请求中的 HTTP ORIGIN 参数在哪里似乎很混乱 我在用着烧瓶 0 10 1 以及HTTP ORIGIN似乎是这个的特点之一object
  • 在f字符串中转义字符[重复]

    这个问题在这里已经有答案了 我遇到了以下问题f string gt gt gt a hello how to print hello gt gt gt f a a gt gt gt f a File
  • 如何在seaborn displot中使用hist_kws

    我想在同一图中用不同的颜色绘制直方图和 kde 线 我想为直方图设置绿色 为 kde 线设置蓝色 我设法弄清楚使用 line kws 来更改 kde 线条颜色 但 hist kws 不适用于显示 我尝试过使用 histplot 但我无法为
  • 类型错误:预期单个张量时的张量列表 - 将 const 与 tf.random_normal 一起使用时

    我有以下 TensorFlow 代码 tf constant tf random normal time step batch size 1 1 我正进入 状态TypeError List of Tensors when single Te
  • Conda SafetyError:文件大小不正确

    使用创建 Conda 环境时conda create n env name python 3 6 我收到以下警告 Preparing transaction done Verifying transaction SafetyError Th
  • 使用 Python 绘制 2D 核密度估计

    I would like to plot a 2D kernel density estimation I find the seaborn package very useful here However after searching
  • 使用其构造函数初始化 OrderedDict 以便保留初始数据的顺序的正确方法?

    初始化有序字典 OD 以使其保留初始数据的顺序的正确方法是什么 from collections import OrderedDict Obviously wrong because regular dict loses order d O
  • 在 Qt 中自动调整标签文本大小 - 奇怪的行为

    在 Qt 中 我有一个复合小部件 它由排列在 QBoxLayouts 内的多个 QLabels 组成 当小部件调整大小时 我希望标签文本缩放以填充标签区域 并且我已经在 resizeEvent 中实现了文本大小的调整 这可行 但似乎发生了某
  • 从列表指向字典变量

    假设你有一个清单 a 3 4 1 我想用这些信息来指向字典 b 3 4 1 现在 我需要的是一个常规 看到该值后 在 b 的位置内读写一个值 我不喜欢复制变量 我想直接改变变量b的内容 假设b是一个嵌套字典 你可以这样做 reduce di
  • Python 类继承 - 诡异的动作

    我观察到类继承有一个奇怪的效果 对于我正在处理的项目 我正在创建一个类来充当另一个模块的类的包装器 我正在使用第 3 方 aeidon 模块 用于操作字幕文件 但问题可能不太具体 以下是您通常如何使用该模块 project aeidon P
  • Python Selenium:如何在文本文件中打印网站上的值?

    我正在尝试编写一个脚本 该脚本将从 tulsaspca org 网站获取以下 6 个值并将其打印在 txt 文件中 最终输出应该是 905 4896 7105 23194 1004 42000 放置的动物 的 HTML span class

随机推荐

  • 警告:“SDK 版本问题”。 Xcode 10.1

    当使用 xcode 10 1 上传我的应用程序时 我收到警告 警告 ITMS 90725 SDK 版本问题 此应用程序是使用 iOS 12 0 SDK 构建的 从 2019 年 3 月开始 提交到 App Store 的所有 iOS 应用程
  • mysql连接用户标志后有空格

    我有一个问题 这个有什么意义空白在用户标志之后 u在 mysql 连接字符串内 mysql u myname pmypass mydb 我的意思是说 如果我之后不传递空格 上面的命令就可以正常工作 u然后将上面的命令写如下 mysql um
  • socket,检测连接丢失

    我正在使用 TCP 连接连接服务器进程和客户端进程 并且我必须检测两台机器之间的物理连接已断开 我正在尝试使用 keepalive 来做到这一点 将默认系统范围值减少为 TCP KEEPIDLE 5TCP KEEPCNT 5TCP KEEP
  • 在 Rust 中,将 &str 拆分为每个包含一个字符的 &str 迭代器的惯用方法是什么?

    如果我想采取 str like aeiou 并将其变成一个迭代器 大致相当于 a e i o u iter 最惯用的方法是什么 我试过做 aeiou split 这对我来说似乎是惯用的 但我很空虚 strs 位于开头和结尾 我试过做 aei
  • 使用perl修改xml标签的属性值

    我有一个很长的 xml 我希望更新其中一个嵌套非常深的标签的属性值 因此不想逐个节点进行操作 此外 目标节点的结构始终不相同 如下所示 输入 XML 为
  • 创建 PHP 登录页面的最佳方法是什么?

    我对 PHP 相当陌生 正在寻找一些有关如何在 PHP 中实现身份验证的最佳实践 我是 Adob e 的传播者 令我烦恼的一件事是人们使用 Flex Flash 作为登录屏幕 因此 我想写一篇博客文章 示例 介绍如何使用 HTML PHP
  • Material Design 的 Side-Menu.Android 中的活动意图

    in https github com Yalantis Side Menu Android https github com Yalantis Side Menu Android 请帮我 当我单击侧面菜单中的每个项目时 如何转到命令 意图
  • Laravel getQueryLog 显示行查询已执行

    正如标题所说 我想知道是否有办法获得getQueryLog函数显示查询行 var dump DB getQueryLog 你不能这样做getQueryLog 但您可以监听查询 生成回溯并最终提取行号 routes php Event lis
  • 如何从点文件中提取子图

    我有一个由名为egypt的软件生成的点文件 点文件包含许多节点和边 如果我用这个点文件画图 由于节点太多 很难看清图片 而我需要的只是从一个节点开始的子图 不需要全图 有没有办法使用这个点文件从指定节点 例如start node 绘制子图
  • 避免注册表 Wow6432Node 重定向

    我尝试在 c 中使用 Microsoft Win32 RegistryKey 插入一些简单的注册表项 但路径会自动更改为 HKEY LOCAL MACHINE SOFTWARE Test to HKEY LOCAL MACHINE SOFT
  • 通过排列两个变量添加计数器列(dplyr)

    我到处寻找了一段时间 但找不到适合我情况的任何解决方案 我有一个数据框 其中混合有 ID 和 VAR 下面我尝试复制一个示例 require dplyr seed 123 N lt 3 T lt 4 id lt rep letters 1
  • 根据控制器操作切换 Devise 身份验证模块

    我有一个 Rails 站点 使用Devise https github com plataformatec devise用于身份验证 我有一页 PhotosController create 需要在没有 cookie 的情况下对用户进行身份
  • 将 CMake 项目导入 Eclipse CDT

    我有一个土生土长的CMake http en wikipedia org wiki CMake项目 我想使用Eclipse http en wikipedia org wiki Eclipse 28software 29IDE 使用它 通过
  • Codeigniter - 使用多个数据库

    数据库 php db default hostname 192 168 2 104 db default username webuser db default password db default database vad db def
  • 如何在运行时更改 slf4j 级别?

    我使用 SLF4j 作为我的日志框架 由 log4j 支持 我的问题是我正在寻找一种在运行时更改记录器的日志记录级别的方法 据我了解 slf4j 不允许直接通过其自己的 API 执行此操作 因此 我必须直接访问日志记录提供程序 我个人认为这
  • 当 AppBar 下没有滚动内容时如何禁用 AppBar 阴影

    在 app bar dart 文件中提到海拔控制应用栏下方阴影的大小 默认情况下 如果应用栏下方没有滚动内容 则不会绘制阴影 这是我的代码 Scaffold appBar AppBar brightness Brightness light
  • jTemplates:变量中的 html

    我想在 jTemplate 变量中包含一些 html 例如 td class numeric T total price td 其中总价格是 12 span 00 span 有什么方法可以让 span 显示为 html 吗 我得到它 mhi
  • C++ 中的对象序列化

    我想序列化 反序列化一些结构化数据 以便通过网络将其发送char buffer 更准确地说 假设我有一条消息类型struct Message struct Message Header header Address address size
  • 删除月份中某天的前导“0” SimpleDateFormat

    2012年1月4日的 0 可以去掉吗 我目前正在使用以下 Java 来获取日期格式 例如 Monday January 04 2012 我希望它看起来像 Monday January 4 2012 Date anotherCurDate n
  • 使用 cython 简单包装 C 代码

    我有许多 C 函数 我想从 python 调用它们 cython 似乎是可行的方法 但我无法真正找到具体如何完成此操作的示例 我的 C 函数如下所示 void calculate daily char db name int grid id