将 .h 文件中的常量导入 python

新手上路,请多包涵

我一直在寻找这个问题的简单答案,但似乎找不到。我宁愿远离任何尚未包含在 Python 2.62.7 中的外部库。

我有 2 个类似于以下内容的 c 头文件:

 //constants_a.h
const double constant1 = 2.25;
const double constant2 = -0.173;
const int constant3 = 13;

 //constants_b.h
const double constant1 = 123.25;
const double constant2 = -0.12373;
const int constant3 = 14;

我有一个 python 类,我想将这些常量导入到:

 #pythonclass.py
class MyObject(object):
    def __init(self, mode):
        if mode is "a":
            # import from constants_a.h, like:
            # self.constant1 = constant1
            # self.constant2 = constant2
        elif mode is "b":
            # import from constants_b.h, like:
            # self.constant1 = constant1
            # self.constant2 = constant2

我也有使用常量的 C 代码,类似于:

 //computations.c
#include <stdio.h>
#include <math.h>
#include "constants_a.h"

// do some calculations, blah blah blah

如何将头文件中的常量导入 Python 类?

头文件 constants_a.h 和 constants_b.h 的原因是我使用 python 来使用常量进行大部分计算,但有一次我需要使用 C 来进行更优化的计算。此时我正在使用 ctypes 将 c 代码包装到 Python 中。我想让常量远离代码,以防万一我需要更新或更改它们,并使我的代码更清晰。我不知道是否有助于注意我也在使用 NumPy,但除此之外,没有其他非标准 Python 扩展。我也愿意接受有关此程序的设计或架构的任何建议。

原文由 Manila Thrilla 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 530
2 个回答

我建议使用正则表达式( re 模块)从文件中解析你想要的信息。

构建一个完整的 C 解析器将是巨大的,但如果您只使用变量并且文件相当简单/可预测/受控,那么您需要编写的内容很简单。

只需注意“陷阱”工件,例如注释掉的代码!

原文由 Emilio M Bumachar 发布,翻译遵循 CC BY-SA 3.0 许可协议

通常,在 C 头文件中 定义 变量是一种糟糕的风格。头文件应该只 声明 对象,将它们的定义留给适当的“.c”源代码文件。

您可能想要做的一件事是声明库全局常量,如 extern const whatever_type_t foo; 并在您的 C 代码中的某处定义(或“实现”)它们(即为它们赋值)(确保您这样做只有一次)。

无论如何,让我们忽略你是 如何 做到的。假设您已经定义了常量并使它们的符号在您的共享对象文件“libfoo.so”中可见。让我们假设您想要从 Python 代码访问 libfoo 中的符号 pi 定义为 extern const double pi = 3.1415926;

现在,您通常使用 ctypes 在 Python 中加载目标文件,如下所示:

 >>> import ctypes
>>> libfoo = ctypes.CDLL("path/to/libfoo.so")

但是你会看到 ctypes 认为 libfoo.pi 是一个函数,而不是常量数据的符号!

 >>> libfoo.pi
<_FuncPtr object at 0x1c9c6d0>

要访问它的值,您必须做一些相当尴尬的事情——将 ctypes 认为是一个函数的东西转换 一个数字。

 >>> pi = ctypes.cast(foo.pi, ctypes.POINTER(ctypes.c_double))
>>> pi.contents.value
3.1415926

在 C 术语中,这模糊地对应于发生的以下事情:你有一个 const double pi ,但有人强迫你只能通过函数指针使用它:

 typedef int (*view_anything_as_a_function_t)(void);
view_anyting_as_a_function_t pi_view = &pi;

你如何处理指针 pi_view 以使用 pi 的值?您将其转换为 const double * 并取消引用它: *(const double *)(pi_view)

所以这一切都非常尴尬。也许我遗漏了一些东西,但我相信这是 ctypes 模块的设计——它主要用于进行 _外部函数调用_,而不是用于访问“外部”数据。在可加载库中导出纯数据符号可以说是很少见的。

如果常量只是 C 宏定义,这将不起作用。通常您无法从外部访问宏定义的数据。它们在编译时被宏扩展,在生成的库文件中没有留下可见的符号, 除非 您也在 C 代码中导出它们的宏值。

原文由 Cong Ma 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题