【问题标题】:Calling custom C subroutines in a Python application在 Python 应用程序中调用自定义 C 子例程
【发布时间】:2018-07-03 18:21:44
【问题描述】:

我有两个自定义编写的 C 例程,我想将它们用作大型 Python 应用程序的一部分。我不希望用纯 Python(或 Cython 等)重写 C 代码,尤其是为了保持速度。

从 Python 代码中使用 C 代码的最简洁、最简单的方法是什么?或者,对我来说,将 C 代码打包以在 Python 源代码中使用的最简洁、最简单的方法是什么?

我知道“最干净”和“最简单”会吸引意见,但我真的只需要一些好的选择来使用 自定义预先编写的代码,而不是描述如何使用的许多其他答案/教程使用完整的 C 库作为 CPython 扩展。

编辑:

已建议使用 Cython 和 ctypes。在我的情况下,哪个是更好的选择?我最初提到的两个例程中的每一个都非常计算密集。它们用于图像计算和重建,因此我的计划是围绕它们的用途构建一个 Python 应用程序(考虑到我在 Python 中已经拥有的其他功能),并根据需要运行 C 代码以进行处理。

【问题讨论】:

  • 使用 Cython 作为胶水;见那里的文档。

标签: python c python-3.x python-3.5 python-c-api


【解决方案1】:

使用 cython 包装您的 C 代码。换句话说,使用 Cython 创建一个 CPython 扩展,它会调用您的 C 代码。

【讨论】:

  • 如果这些 C 函数非常庞大且计算量很大,这仍然是一个好主意吗?
  • 我不明白为什么不呢?您将按原样调用您的 C 代码......谁在乎它是否密集?我完全不明白你的担忧@questionable_code
  • 我很抱歉。我试图推断我应该更有信心地尝试两条路线(cython 或 ctypes)中的哪一条,因为后者在下面被建议。
  • Cython 代码是可维护的高级代码,在编译时会转换为 C 并作为二进制扩展链接到 python - 这是最礼貌的解决方案并且非常高效。 ctypes 感觉就像 cython 旁边的一个 hack,它将产生一个完整的企业级 python 扩展。 @questionable_code
  • @questionable_code:如果做得对,Cython 的工作与原始 C 扩展相同,但工作量要少得多。您可以检查生成的 C/C++ 代码,看看它是否正常完成(生成的代码往往非常冗长,但编译器的优化器会在最终扩展中对其进行清理)。
【解决方案2】:

您可以直接从 python 调用 C。从这里提取的示例:https://www.csestack.org/calling-c-functions-from-python/

from ctypes import *
libCalc = CDLL("./libcalci.so")

#call C function to check connection
libCalc.connect() 

#calling randNum() C function
#it returns random number
varRand = libCalc.randNum()
print "Random Number:", varRand, type(varRand)

#calling addNum() C function
#it returns addition of two numbers
varAdd = libCalc.addNum(20,30)
print "Addition : ", varAdd

【讨论】:

  • 请注意,当通过ctypes单个 调用完成大部分工作时,此方法效果最佳,并且 工作很重要;如果您要进行大量小型调用,而工作量很小,ctypes 会引入真正的 C 扩展可以避免的非平凡开销。
  • @ShadowRanger 如果我的例程计算量很大且规模很大,那么这是一条不错的路径吗?
  • 如果工作不复杂,最好先用 Python 编写它,使这个问题变得毫无意义。我推断c代码复杂而繁重,ctypes是这方面最好的方法。
  • @questionable_code:是的,ctypes 开销通常在数百纳秒到个位数微秒,最坏的情况是;如果您每次调用都在 C 层做一毫秒的工作,那么 ctypes 开销是毫无意义的。诀窍在于库公开了大量对 Python 有用的小调用,但在 Python 中不易有效地重新实现。诸如简单的 GMP 数学函数之类的东西;重新实现很痛苦,但相对于ctypes 开销来说是微不足道的工作(在这种特殊情况下,gmpy2 是可行的方法,但存在类似的没有包装器的库)。
猜你喜欢
  • 2020-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-16
  • 2016-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多