Question: These are simple variable declarations in cpp, how do I do it in Python ctypes? B *C = (B *) A; D *E = (D *)(A + sizeof(B));  Assume that B and D are structs and A is uint8_t A[42];. Where do I start from here? I tried using cast functions but maybe I'm wrong, can you help me? from ctypes import POINTER, byref, addressof, sizeof, cast C = cast(byref(A), POINTER(B)).contents E = cast(addressof(A) + sizeof(B), POINTER(D)).contents 

Answer: Listing [Python.Docs]: ctypes - A foreign function library for Python. In short, to:  Dereference a pointer - cts_ptr_var.contents  Reference a variable (to a pointer) - ctypes.pointer(cts_var) (to later pass it as an argument to a function - ctypes.byref(cts_var))  Get its (C) address - ctypes.addressof(cts_var)   Now, regarding your question, a nicer way would be to use (each CTypes type's) from_address (and avoid those pointers). code00.py: #!/usr/bin/env python import ctypes as cts import sys I8Arr42 = cts.c_uint8 * 42 class S0(cts.Structure): if len(sys.argv) > 1: # @TODO - cfati: Lame (for demo purposes only) _pack_ = 1 _fields_ = ( ("ui80", cts.c_uint8), ("ui81", cts.c_uint8), ("ui320", cts.c_uint32), ("ui82", cts.c_uint8), ) PS0 = cts.POINTER(S0) class S1(cts.Structure): if len(sys.argv) > 1: # @TODO _pack_ = 1 _fields_ = ( ("ui80", cts.c_uint8), ("ui320", cts.c_uint32), ("ui81", cts.c_uint8), ) PS1 = cts.POINTER(S1) def main(*argv): size0 = cts.sizeof(S0) arr = I8Arr42(*range(42)) #arr = I8Arr42() print(arr, hex(cts.addressof(arr)), hex(id(arr))) print(f"Initial values: {arr[0]}, {arr[size0]}, {arr[-1]}\n") print("FromAddress") s00 = S0.from_address(cts.addressof(arr)) # Initialize structure from memory contents at address print("First structure:") for name, _ in s00. _fields_: print(f" {name}: 0x{getattr(s00, name):02X}") s10 = S1.from_address(cts.addressof(arr) + size0) # Initialize structure from memory contents at address print("\nSecond structure:") for name, _ in s10. _fields_: print(f" {name}: 0x{getattr(s10, name):02X}") s00.ui80 = 100 s10.ui80 = 101 print(f"\nModified values: {arr[0]}, {arr[size0]}, {arr[-1]}\n") print("\nCast") s01 = cts.cast(cts.addressof(arr), PS0).contents print("First structure:") for name, _ in s01. _fields_: print(f" {name}: 0x{getattr(s01, name):02X}") s11 = cts.cast(cts.addressof(arr) + size0, PS1).contents print("\nSecond structure:") for name, _ in s11. _fields_: print(f" {name}: 0x{getattr(s11, name):02X}") s01.ui80 = 200 s11.ui80 = 201 print(f"\nModified values: {arr[0]}, {arr[size0]}, {arr[-1]}\n") if __name__ == "__main__": print( "Python {:s} {:03d}bit on {:s}\n".format( " ".join(elem.strip() for elem in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform, ) ) rc = main(*sys.argv[1:]) print("\nDone.\n") sys.exit(rc)  Output:  [cfati@CFATI-5510-0:e:\Work\Dev\StackExchange\StackOverflow\q078494178]> sopr.bat ### Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ### [prompt]> :: No argument - default (structure) packing [prompt]> "e:\Work\Dev\VEnvs\py_pc064_03.10_test0\Scripts\python.exe" ./code00.py Python 3.10.11 (tags/v3.10.11:7d4cc5a, Apr 5 2023, 00:38:17) [MSC v.1929 64 bit (AMD64)] 064bit on win32 <__main__.c_ubyte_Array_42 object at 0x000001E9E8C04140> 0x1e9e8fffdb0 0x1e9e8c04140 Initial values: 0, 12, 41 FromAddress First structure: ui80: 0x00 ui81: 0x01 ui320: 0x7060504 ui82: 0x08 Second structure: ui80: 0x0C ui320: 0x13121110 ui81: 0x14 Modified values: 100, 101, 41 Cast First structure: ui80: 0x64 ui81: 0x01 ui320: 0x7060504 ui82: 0x08 Second structure: ui80: 0x65 ui320: 0x13121110 ui81: 0x14 Modified values: 200, 201, 41 Done. [prompt]> :: Dummy argument - #pragma pack(1) [prompt]> "e:\Work\Dev\VEnvs\py_pc064_03.10_test0\Scripts\python.exe" ./code00.py dummy Python 3.10.11 (tags/v3.10.11:7d4cc5a, Apr 5 2023, 00:38:17) [MSC v.1929 64 bit (AMD64)] 064bit on win32 <__main__.c_ubyte_Array_42 object at 0x000001A85B484140> 0x1a85b87ff30 0x1a85b484140 Initial values: 0, 7, 41 FromAddress First structure: ui80: 0x00 ui81: 0x01 ui320: 0x5040302 ui82: 0x06 Second structure: ui80: 0x07 ui320: 0xB0A0908 ui81: 0x0C Modified values: 100, 101, 41 Cast First structure: ui80: 0x64 ui81: 0x01 ui320: 0x5040302 ui82: 0x06 Second structure: ui80: 0x65 ui320: 0xB0A0908 ui81: 0x0C Modified values: 200, 201, 41 Done.   For future tasks, you might want to check [SO]: C function called from Python via ctypes returns incorrect value (@CristiFati's answer) for a common pitfall when working with CTypes (calling functions).