Python ctypes:byref()未反映更新后的值

时间:2020-07-08 15:33:46

标签: python c python-3.x pass-by-reference ctypes

我正在用python编写一些C API的包装。我能够编写包装器,并且当我尝试从另一个程序调用该包装器以访问API时,指针变量更改后的值不会在python变量中得到更新。

我来自pythonWrapper.py的API代码:

import ctypes
from enum import Enum

_obj = cdll.LoadLibrary(./sharedObj.so)

#some enums and structure will be here like :

class structwrap(Structure):
  _fields_ = [("id", c_int),
              ("type", c_int),
              ("state", c_int)]
  def __init__(self):
      self.id = 0
      self.type = 0
      self.state = 0


def wrappedAPI(structwrapList, count):
    _obj.wrappedAPI.argtypes = [ctypes.POINTER(structwrapList),ctypes.POINTER(c_int)]
    _obj.wrappedAPI.restype = int
    if not structwrapList:
        structwrapList = structwrap()
    ret = _obj.orgAPI(byref(structwrapList),byref(c_int(count)))
    print (count)
    return ret

相应的C代码是:

typedef struct structOrg
{
    int                 id;     /* index */
    dvDevIcType_t       type;  /* type */
    dvDevExecState_t    state;   /* state */
}structOrg_t;


int orgAPI(structOrg_t *structList, int *count){
...
//count value is being changed here. like count = count+1
}

上面的python文件被从test.py调用:

from ctypes import *
from  pythonWrapper import *
count =0
ret = dvDeviceGet(None, count)
print (count)

输出ret成功,但count值仍为0,但在c函数中将其更改为2。但是在python变量中,它仍为0。

有人可以在这里指出我的错误吗?

2 个答案:

答案 0 :(得分:1)

byref(c_int(count))创建一个新的c_int并将一个指针传递给那个count不受影响。 count是普通的Python int,不是C int或C int的包装对象。

答案 1 :(得分:0)

一些重构:

_obj = cdll.LoadLibrary(./sharedObj.so)

# Only need to do this once, not every time inside the function
_obj.wrappedAPI.argtypes = [ctypes.POINTER(structwrapList),ctypes.POINTER(c_int)]
_obj.wrappedAPI.restype = ctypes.c_int # Needs to be a ctypes type.

def wrappedAPI(structwrapList,count):
    if not structwrapList:
        structwrapList = structwrap()
    c_count = ctypes.c_int(count) # Create a ctypes type to pass by reference
    ret = _obj.orgAPI(byref(structwrapList),ctypes.byref(c_count))
    return ret,c_count.value

致电:

ret,count = dvDeviceGet(None, count)