如何使用ctypes动态分配数组并将地址分配给共享库中定义的指针?

问题描述 投票:0回答:1

我的库是从simulink生成的,看起来像这样:

lib.h

extern double *params1;
extern double *params2; 

typedef struct {
  unsigned int params1_len;
  unsigned int params2_len;
} P_model_T;

lib.c

double *params1;
double *params2;

P_model_T model_params = { 0, 0 };

void step(double in, double *out) {
  // some code using the parameter arrays
}

我打算像这样从python使用它,并假设在调用set_params函数之前总是会调用step(因此初始化所需的参数数组:]

lib_wrapper.py

from ctypes import *

import numpy as np

class LibWrapper:
  def __init__(self):
    self._library = CDLL("lib.dll")
    self._param_struct = ModelParameters.in_dll(self._library, 'model_params')

  def step(self, _in):
    out = c_double()
    self._library.step(c_double(_in), byref(out))
    return out

  def get_params(self, param_name):
    array_len = getattr(self._param_struct, f'{param_name}_len')  # get length of parameter array
    array_p = POINTER(c_double * array_len).in_dll(self._library, param_name)  # get actual array from library
    return np.array(array_p.contents)  # copy and return

  def set_params(self, param_name, data):
    array = (c_double * len(data))(*data)
    setattr(self._library, param_name, pointer(array))

class ModelParameters(Structure):
    _fields_ = [('params1_len', c_uint32),
                ('params2_len', c_uint32)]

我的问题是关于set_params的实现:据我了解,我的解决方案没有将array的地址分配给dll中我的实际params1 / params2变量,但它仅更改了dll表示形式内部ctypes。因此,当我调用step函数时,总是遇到访问冲突,因为我的参数变量仍指向0x0000000000000000。

将我分配的数组分配给共享库中的params变量的正确方法是什么?

跟进:会有更简洁的方式来写我的get_params吗?设置它们后,ctypes可以以某种方式“记住”我的params变量的类型,这样就不必强制转换它们了吗?

我的库是从simulink生成的,看起来像这样:lib.h extern double * params1; extern double * params2; typedef struct {unsigned int params1_len; unsigned int params2_len; } ...

python c ctypes
1个回答
0
投票

我让它正常工作,但这是一个把戏。您的set_params未按in_dll查找参数,因此无效。同样,即使使用in_dll访问内容,也只是试图取消对已经存在的空指针的引用,因此我需要获取参数的地址才能更改空指针。我使用以下DLL和Python代码进行测试:

© www.soinside.com 2019 - 2024. All rights reserved.