【问题标题】:Access a global pointer in C from python using ctypes使用 ctypes 从 python 访问 C 中的全局指针
【发布时间】:2020-02-13 11:23:20
【问题描述】:

我知道如果我有一个全局变量(比如说一个名为 N 的双精度变量),我可以使用以下方法读取它:

from ctypes import c_double, CDLL
c_lib = CDLL('path/to/library.so')
N = c_double.in_dll(c_lib, "N").value

但是如果我的变量是一个指针呢?如何将指针的内容读入 python 列表?

为了清楚起见,N在共享库中的声明方式如下:

double N = 420.69;

【问题讨论】:

标签: python c pointers global-variables ctypes


【解决方案1】:

鉴于此 (Windows) DLL 源:

int ints[10] = {1,2,3,4,5,6,7,8,9,10};
double doubles[5] = {1.5,2.5,3.5,4.5,5.5};

__declspec(dllexport) char* cp = "hello, world!";
__declspec(dllexport) int* ip = ints;
__declspec(dllexport) double* dp = doubles;

您可以通过以下方式访问这些导出的全局变量:

>>> from ctypes import *
>>> dll = CDLL('./test')
>>> c_char_p.in_dll(dll,'cp').value
b'hello, world!'
>>> POINTER(c_int).in_dll(dll,'ip').contents
c_long(1)
>>> POINTER(c_int).in_dll(dll,'ip')[0]
1
>>> POINTER(c_int).in_dll(dll,'ip')[1]
2
>>> POINTER(c_int).in_dll(dll,'ip')[9]
10
>>> POINTER(c_int).in_dll(dll,'ip')[10]   # Undefined behavior, past end of data.
0
>>> POINTER(c_double).in_dll(dll,'dp')[0]
1.5
>>> POINTER(c_double).in_dll(dll,'dp')[4]
5.5
>>> POINTER(c_double).in_dll(dll,'dp')[5] # Also UB, past end of data.
6.9532144253691e-310

要获取列表,如果您知道大小:

>>> list(POINTER(c_int * 10).in_dll(dll,'ip').contents)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

【讨论】:

  • 谢谢马克!这完美地工作。您是否偶然知道它在 ctypes 中是否存在 fftw_complex 变量类型的等价物?现在我正在使用c_double 访问一个复杂的变量,它可以工作,但感觉不对。无论如何,再次感谢您的完整回答。
  • @FrancescoBoccardo 您可以使用fftw_complex = c_double * 2 来表示该类型,或者声明class fftw_complex(Structure): _fields_ = ('real',c_double),('imag',c_double) 以更像一个结构来访问它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-24
  • 2014-01-28
  • 2014-07-21
  • 1970-01-01
相关资源
最近更新 更多