【问题标题】:OS X: python ctypes global variablesOS X:python ctypes 全局变量
【发布时间】:2015-08-01 01:32:57
【问题描述】:

我正在尝试为使用 C99 标准编写的项目创建 Python ctypes 绑定。当前的 C 代码将一些全局变量(例如 bcd)与顶级函数(例如 mod_run)结合使用。

示例:model.c

#include <mod_def.h>
#include <mod_run.h>

struct_b *b;
int       d

int
mod_run(int                  rec,
        double               state,
        struct_a            *a)
{
    extern struct_c     c;

// code that uses a, b, c, d, rec, state
// and functions defined in mod_def.h and mod_run.h

}

我已使用setuptools.extension 模块成功创建了一个共享对象(例如model.so),但无法使用ctypes.cdll.LoadLibrary 加载该对象。

In [1]: from ctypes import *

In [2]: cdll.LoadLibrary('model.so')

OSError: dlopen(model.so, 6): Symbol not found: _X
  Referenced from: model.so
  Expected in: dynamic lookup

其中X 是在mod_def.h 中声明的全局变量:

extern size_t X;

最后,我的问题。我是否需要围绕mod_run 创建一个包装器,以便导出示例代码中定义的每个全局变量?或者是否有可能以某种方式加载共享对象,而无需定义X

我已经查看了这些相关主题,但没有找到任何解决我问题的方法:

更新(2015 年 5 月 20 日):

我如何构建共享对象:

setup(name='model',
      ...
      ext_modules=[Extension(
          'model',
          sources=sources,  # list of c sources using absolute paths
          include_dirs=includes,  # list of include directories using absolute paths
          extra_compile_args=['-std=c99'],
          # extra_link_args=['-lmodule_with_globals']  # does not build with this option: ld: library not found for -lmodule_with_globals
          )])

使用 OSX 10.10.3 和 Python 3.4.3 :: Anaconda 2.2.0 (x86_64)。

【问题讨论】:

  • 我怀疑您需要在LoadLibrary 调用中使用相对路径(例如./model.so),否则它只会在系统目录中搜索文件。
  • @Frxstrem - 我在构建中使用绝对路径。我也不认为这是路径问题,因为X 应该在model.so 中。
  • @eryksun - 感谢您的想法。你有一个如何使用-lmodule_with_globalssetuptools 的例子吗?如上所示添加它(更新 05/20/2015)不起作用。你的第二个想法也是如此。
  • @eryksun - 呃。现在我懂了。我正在使用的代码是一个独立的 c 模块,因此不需要与其他模块进行任何链接。
  • 哦,如果变量定义在同一个模块中,请不要将它们声明为extern

标签: python c macos ctypes setuptools


【解决方案1】:

问题在于变量X 是在头文件中定义的,但从未在代码中的任何位置分配。 extern size_t X;

为了解决这个问题,我创建了一个名为 globals.c 的包装文件,并在其中简单地说:

// globals.c
#include <mod_def.h>
#include <mod_run.h>

size_t X;
// allocation of other global variables

就这样,

from ctypes import *
# load the library (this was failing before)
lib = cdll.LoadLibrary('model.so')

# create a python variable that maps to the global X
X = c_sizet.in_dll(lib, 'X')
# assign a value to the global X
X.value = 2

分配可能位于现有源文件之一的标头中,但在我的情况下,这就是我们现在希望模块工作的方式。

【讨论】:

    猜你喜欢
    • 2019-07-26
    • 2018-10-23
    • 1970-01-01
    • 1970-01-01
    • 2015-06-12
    • 2019-07-24
    • 2017-11-08
    • 1970-01-01
    相关资源
    最近更新 更多