Closed qb-0 closed 1 year ago
seems like a good idea to me
made a new branch to track work on this and added the read methods in https://github.com/srounet/Pymem/tree/impl-%23101
I just figured out that you don't even need to create a buffer and move the memory. You can pass the c type directly to ReadProcessMemory
. Increases the performance even more.
def read(handle: int, address: int, c_type, get_py_value=True) -> Any:
size = ctypes.sizeof(c_type)
if ReadProcessMemory(handle, ctypes.c_void_p(address), ctypes.byref(c_type), size, None) == 0:
raise OSError(GetLastError())
if get_py_value:
return c_type.value
return c_type
nice, also did you see a performance improvement when using this method for writing?
I didn't tried yet. I could write up some tests tomorrow. But I guess the result will be pretty much the same as you don't need to create a byte array from the python value:
def write(handle, address: int, data: Any) -> int:
result = ctypes.c_size_t()
WriteProcessMemory(
handle,
ctypes.cast(address, ctypes.c_void_p),
ctypes.cast(ctypes.byref(data), ctypes.c_void_p),
size,
ctypes.byref(result)
)
return result.value
def write_int(handle, address, value):
return write(handle, address, ctypes.c_int(value)) > 0
I'll remove the buffer from the read method and add write tomorrow, then just need to test it and it should be good to go
So this are my results for writing.
[R] pyMem (Local: {'name': 'unarmed', 'health': 100, 'pos_x': 182.0, 'pos_y': 73.0, 'pos_z': 3.5}): Memory: 1.7718544006347656 sec
[W] pyMem 2.9343247413635254 sec
[R] cTypes Mem (Local: {'name': 'unarmed', 'health': 101, 'pos_x': 182.0, 'pos_y': 73.0, 'pos_z': 3.5}): Memory: 1.0322694778442383 sec
[W] cTypes Mem 2.876091957092285 sec
[R] cTypes Mem Struct (Local: {'name': 'unarmed', 'health': 102, 'pos_x': 182.0, 'pos_y': 73.0, 'pos_z': 3.5}): Memory: 0.24591755867004395 sec
[W] cTypes Mem Struct 0.7125911712646484 sec
https://github.com/qb-0/RW-Mem-C/blob/master/compare_speed.py
The current behavior of pymem is to read / write bytes into a buffer and unpacking / packing the binary data with struct. This could be optimized by copying the bytes into a ctype (with memmove) and using the value field. This way the whole unpacking / packing process can be skipped.
Reading an Integer would then look like:
My current tests on Assault Cube show some small speedup's on simple memory operations.
The real advantage shows up when you read whole c structures which could be used this way.
The whole project and the testing file can be reviewed here: https://github.com/qb-0/RW-Mem-C