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

Man*_*lla 15 c python ctypes header constants

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

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

//constants_a.h
const double constant1 = 2.25;
const double constant2 = -0.173;
const int constant3 = 13;
Run Code Online (Sandbox Code Playgroud)

...

//constants_b.h
const double constant1 = 123.25;
const double constant2 = -0.12373;
const int constant3 = 14;
Run Code Online (Sandbox Code Playgroud)

...

我有一个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
Run Code Online (Sandbox Code Playgroud)

...

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

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

// do some calculations, blah blah blah
Run Code Online (Sandbox Code Playgroud)

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

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

Con*_* Ma 15

通常,在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")
Run Code Online (Sandbox Code Playgroud)

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

>>> libfoo.pi
<_FuncPtr object at 0x1c9c6d0>
Run Code Online (Sandbox Code Playgroud)

要获得它的价值,你必须做一些相当尴尬的事情 - 将一个ctypes认为是函数的东西转换一个数字.

>>> pi = ctypes.cast(foo.pi, ctypes.POINTER(ctypes.c_double))
>>> pi.contents.value
3.1415926
Run Code Online (Sandbox Code Playgroud)

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

typedef int (*view_anything_as_a_function_t)(void);
view_anyting_as_a_function_t pi_view = &pi;
Run Code Online (Sandbox Code Playgroud)

你用指针做什么pi_view来使用pi?的值?你把它作为一个const double *并将其取消引用:*(const double *)(pi_view).

所以这一切都很尴尬.也许我错过了一些东西,但我相信这是通过ctypes模块的设计- 它主要用于进行外部函数调用,而不是用于访问"外来"数据.在可加载库中导出纯数据符号可能很少见.

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

  • 好吧,我刚刚发现了这种非笨拙的方法:http://python.net/crew/theller/ctypes/tutorial.html#accessing-values-exported-from-dlls你可以试试`pi = ctypes.c_double (Python代码中的libfoo,"pi")` 这将返回一个`ctypes.c_double`实例,您可以通过`pi.value`访问它的值. (3认同)

Emi*_*har 11

我建议使用正则表达式(re模块)来解析文件中所需的信息.

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

只要注意'gotcha'文物,例如注释掉的代码!

  • 看看自1992年以来修订的[Tools/Scripts/h2py.py](http://hg.python.org/cpython/log/70274d53c1dd/Tools/scripts/h2py.py)脚本. (3认同)