【问题标题】:How can I reference #defines in a C file from python?如何在 python 的 C 文件中引用#defines?
【发布时间】:2012-08-27 18:22:43
【问题描述】:

我有一个 C 文件,其中包含一堆我想从 python 中引用的位的#defines。它们太多了,我宁愿不将它们复制到我的 python 代码中,而是有一种可接受的方法可以直接从 python 引用它们?

注意:我知道我可以打开头文件并解析它,这很简单,但如果有更pythonic的方式,我想使用它。

编辑:

这些是非常简单的#defines,用于定义掩码中位的含义,例如:

#define FOO_A 0x3
#define FOO_B 0x5

【问题讨论】:

标签: python-c-api python-c-extension


【解决方案1】:

在 C .h 文件仅包含 #defines 的假设下运行(因此没有任何外部可链接),那么以下内容适用于 swig 2.0 (http://www.swig.org/) 和 python 2.7(已测试)。假设包含刚刚定义的文件名为 just_defines.h,如上:

#define FOO_A 0x3
#define FOO_B 0x5

然后:

swig -python -module just just_defines.h ## generates just_defines.py and just_defines_wrap.c
gcc -c -fpic just_defines_wrap.c -I/usr/include/python2.7 -I. ## creates just_defines_wrap.o
gcc -shared just_defines_wrap.o -o _just.so ## create _just.so, goes with just_defines.py

用法:

$ python 
Python 2.7.3 (default, Aug  1 2012, 05:16:07) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import just
>>> dir(just)
['FOO_A', 'FOO_B', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '_just', '_newclass', '_object', '_swig_getattr', '_swig_property', '_swig_repr', '_swig_setattr', '_swig_setattr_nondynamic']
>>> just.FOO_A
3
>>> just.FOO_B
5
>>> 

如果 .h 文件还包含入口点,那么您需要链接到某个(或更多)库以解析这些入口点。这使解决方案变得更加复杂,因为您可能必须寻找正确的库。但是对于“只定义案例”,您不必担心这一点。

【讨论】:

  • 这个方法效果很好!我需要决定是否值得花时间编写一些简单的 C 来与这个头文件交互。我需要手动解析 C 标头可能会更简单。
【解决方案2】:

您可能会对 Python 源代码压缩包的 Tools/scripts 目录中的 h2py.py 脚本感到幸运。虽然它不能处理复杂的预处理器宏,但它可能足以满足您的需求。

下面是脚本顶部的功能描述:

阅读#define 并翻译成 Python 代码。 处理#include 语句。 使用一个参数处理#define 宏。 任何无法识别或无法转化为有效的内容 Python 被忽略。

没有文件名参数,充当过滤器。 如果给出了一个或多个文件名,则输出将写入相应的 本地目录中的文件名,转换为全大写,带有 扩展名为“.py”。

通过传递一个或多个“-i regular_expression”形式的选项 您可以指定要忽略的其他字符串。这很有用 例如忽略对 u_long 的强制转换:只需指定“-i '(u_long)'”。

【讨论】:

    【解决方案3】:

    #defines 是宏,在 C 编译器的预处理器之外没有任何意义。因此,它们是世界各地多语言程序员的祸根。 (例如,请参阅两周前的这个 Ada 问题:Setting the license for modules in the linux kernel)。

    没有通过 C 预处理器运行你的源代码,真的没有很好的方法来处理它们。我通常只是弄清楚他们评估的内容(在复杂的情况下,通常没有比实际编译和运行该死的代码更好的方法来做到这一点!),并将该值硬编码到我的程序中。

    (其中一个)烦人的部分是 C 编码器认为 C 预处理器是一个非常简单的小东西,他们经常使用它甚至没有考虑过。结果,他们往往会惊讶于它会给互操作性带来很大的问题,而我们可以相当容易地处理 C 给我们带来的大多数其他问题。

    在上面显示的简单案例中,到目前为止,最简单的处理方法是将相同的两个值编码到 Python 程序中某个地方的常量中。如果跟上变化很重要,那么编写一个 Python 程序将这些值从文件中解析出来可能不会太麻烦。但是,您必须意识到您的 C 代码只会在编译时重新评估这些值,而您的 python 程序会在它运行时执行它(因此可能应该只在 C 代码也被编译时运行)。

    【讨论】:

    • 我认为对于许多人来说,您建议的简单方法会起作用,解析标题或将#defines 引导到编辑器中并进行搜索/替换以将它们转换为 python 常量,具体取决于标题可能会改变。
    【解决方案4】:

    如果您正在编写扩展模块,请使用http://docs.python.org/3/c-api/module.html#PyModule_AddIntMacro

    【讨论】:

      【解决方案5】:

      我遇到了几乎完全相同的问题,因此编写了一个 Python 脚本来解析 C 文件。它旨在重命名以匹配您的 c 文件(但使用 .py 而不是 .h)并作为 Python 模块导入。

      代码:https://gist.github.com/camlee/3bf869a5bf39ac5954fdaabbe6a3f437

      例子:

      配置.h

      #define VERBOSE 3
      #define DEBUG 1
      #ifdef DEBUG
          #define DEBUG_FILE "debug.log"
      #else
          #define NOT_DEBUGGING 1
      #endif
      

      从 Python 中使用:

      >>> import configuration
      >>> print("The verbosity level is %s" % configuration.VERBOSE)
      The verbosity level is 3
      >>> configuration.DEBUG_FILE
      '"debug.log"'
      >>> configuration.NOT_DEBUGGING is None
      True
      

      【讨论】:

        猜你喜欢
        • 2010-12-13
        • 2011-03-12
        • 2010-10-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-11
        • 2014-04-07
        • 2022-06-15
        相关资源
        最近更新 更多