kpk
kpk

Reputation: 162

Python ctypes : byref() is not reflecting the updated value

I am writing wrapper for some C API's in python. I am able to write the wrapper and when i am trying to call that wrapper from another program to access the API, the pointer variable changed value is not getting updated in python variable.

My API code from pythonWrapper.py :

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

The corresponding C code is :

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
}

The above python file is being called called from test.py :

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

The output ret is getting successful but count value is still 0 but inside c function it is being changed say 2. but in python variable it is still 0.

Can someone point my mistake here?

Upvotes: 0

Views: 1438

Answers (2)

Mark Tolonen
Mark Tolonen

Reputation: 177971

A little refactoring:

_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

Call with:

ret,count = dvDeviceGet(None, count)

Upvotes: 0

user2357112
user2357112

Reputation: 281594

byref(c_int(count)) creates a new c_int and passes a pointer to that. count is unaffected. count is an ordinary Python int, not a C int or a wrapper object for a C int.

Upvotes: 1

Related Questions