用ctypes访问内存地址的数据

2024-04-16 13:05:31 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试为一个旧的C程序创建一个Python包装器,它接受输入作为指针。在这一点上,我可以让程序运行,但不知道如何返回指定指针处的值。在

这是一个简化的C脚本:

#include <stdlib.h>

void cprogram(double *wts, double *res, int *kks, int n, double *ex) {
  int m;
  m=n+1;
  res[0]=1.0;
  kks[0]=1.0;}

这是我简化的Python代码:

^{pr2}$

我尝试过类似print tmp[1].wts[1]print tmp[2]的命令,但这只打印内存地址,而不打印值(或者像2.15880221124e-314这样不正确的难以置信的小值)。我想能够返回wts值的列表。在


Tags: 程序脚本程序运行includerestmpintdouble
1条回答
网友
1楼 · 发布于 2024-04-16 13:05:31

您的C函数返回void,而不是CONTEXT *。因此,您的代码只是将未初始化的随机内存强制转换为CONTEXT *,然后尝试取消对它的引用。在

最重要的是,即使它通过引用返回了一个CONTEXT对象,tmp[1]也会试图在对象之后删除内存,所以它仍然是垃圾。在

当你试图将随机内存解释为双精度时,你会得到一些分段错误或值,比如2.15880221124e-314如果你运气好,你会得到正确的外观,但是仍然是随机值,比如0.0。在


同时,由于您的C函数在适当的地方修改了它的参数,所以您不需要在这里做任何花哨的事情。只需使用传入的变量。在

所以:

def runner():
    kk = (1,2,3)
    n = 3
    mm = n + 1
    wts = (c_double * n)(1, 1, 1)
    res = (c_double * mm)(0)
    kks = (c_int * len(kk))(*kk)
    n = c_int(n)
    ex = c_double(0)

    libc.cprogram.restype = None

    libc.cprogram(wts, res, kks, n, ex)

    print wts[1]

这样就可以打印出1.0。在


如果您的C函数返回一个与您的CONTEXT结构匹配的CONTEXT结构数组,那么这一切都可以正常工作。例如:

^{pr2}$

编译它,运行现有的Python脚本,添加一个print tmp[1].wts[1],它将输出2.0。在


最后,为了您的后续工作,首先让我们将C代码改为int *n,其中*n是输入:

void cprogram(double *wts, double *res, int *kks, int *n, double *ex) {
  int m;
  m=*n+1;
  res[0]=1.0;
  kks[0]=1.0;}

现在,要从Python调用它,必须创建一个c_int并传递一个指向它的指针。由于您已经完成了前半部分(这在设置argtypes之前是不必要的……但是现在是必须的,这很方便),所以只需一行更改:

libc.cprogram(wts, res, kks, pointer(n), ex)

如果n是一个in-out参数,这甚至可以工作。在


但实际上,您根本不需要从Python中看到指针对象;使用它所做的唯一事情就是创建它以传递给函数,然后让它被收集起来。要传递一个C指针而不创建ctypes指针对象(即使n是一个in-out参数,它仍然有效),请使用byref

libc.cprogram(wts, res, kks, byref(n), ex)

相关问题 更多 >