Mohan
Mohan

Reputation: 11

How to change structure fields using ctypes python pointers

Below is the code where I'm accessing the values of dll using ctypes.

My intention is to store the structure fields addresses. Whenever the values in the structure changes ,I can access the addresses and get changed values.

DUMMY_DLL_PATH = "dummyModel.dll"

class MyStruct(ctypes.Structure):  
    _fields_ = [("field_one", ctypes.c_int),  
                ("field_two", ctypes.c_int)]  

d_m = ctypes.cdll.LoadLibrary(DUMMY_DLL_PATH)  

d_i = MyStruct.in_dll(d_m,"dummy_In")  

in_field = ctypes.c_int(d_i.field_one)  

#storing the address  
b = ctypes.addressof(in_field)  
b_v = ctypes.cast(b,ctypes.POINTER(ctypes.c_int))  

k= b_v.contents   

print 'before',d_i.field_one,k.value  
#changing the value  
d_i.field_one = 10  

print 'After',d_i.field_one,k.value  

Output:

Before 0 0  
After 10 0  

Through pointers, the values are not getting changed.remains 0

Upvotes: 1

Views: 2675

Answers (1)

Mark Tolonen
Mark Tolonen

Reputation: 177795

The problem is in_field is a new c_int object occupying different memory than the original structure. What you want is c_int.from_buffer (docs) which shares the memory of the original object. Here's an example:

Windows DLL source x.c compiled with cl /LD x.c:

struct MyStruct
{
    int one;
    int two;
};

__declspec(dllexport) struct MyStruct myStruct = {1,2};

Python script:

from ctypes import *

class MyStruct(Structure):
    _fields_ = [
        ("one", c_int),
        ("two", c_int)]
    def __repr__(self):
        return 'MyStruct({},{})'.format(self.one,self.two)

dll = CDLL('x')
struct = MyStruct.in_dll(dll,"myStruct")
alias1 = c_int.from_buffer(struct, MyStruct.one.offset)
alias2 = c_int.from_buffer(struct, MyStruct.two.offset)
print struct
print 'before',alias1,alias2
struct.one = 10
struct.two = 20
print 'after',alias1,alias2

Output:

MyStruct(1,2)
before c_long(1) c_long(2)
after c_long(10) c_long(20)

Upvotes: 4

Related Questions