Create a file modify.h
, with the content:
void modify(int p, int v);
Create a file modify.c
, with the content:
#include "modify.h"
void modify(int p, int v) {
*(int * )(p) = v;
}
Create a file modify.pyx
, with the content:
cdef extern from "modify.h"
void modify(int p, int v)
def py_modify(p, v):
modify(p, v)
For example numpy array exposes raw address of array buffer, so you can access/modify the value like this:
import numpy as np
import ctypes
a = np.random.rand(2, 3)
addr = a.__array_interface__['data'][0]
p = ctypes.c_void_p(addr)
pf = ctypes.cast(p, ctypes.POINTER(ctypes.c_double))
assert pf[0] == a[0, 0]
assert pf[1] == a[0, 1]
assert pf[3] == a[1, 0]
but you cannot easily apply this trick to normal python variable like int, for id() returns the start address of the python object, not the exact location where the value is stored, check this:
from ctypes
import *
a = 123456
p = cast(c_void_p(id(a)), POINTER(c_int))
print(p[: 10])
from the result we can see the value is actually at offset 6*4=24
[1, 0, -1792371528, 127, 1, 0, 123456, 1, 1, 0]
Furthermost above all address is Integer but you may saw many times that the memory address is written in hexadecimal format.,As a result above 10 digits decimal value gives the memory reference of variables var1 and var2. You may get the different value of address based on your system., Above all addresses can be converted to hexadecimal format using hex function.,You can also do the same for finding the address similarly for a float, string, function or an object. Because when you initialize a variable compiler seems to reserve the memory space for them on a different address value.
For example
var1 = 10 print(id(var1)) var2 = 12 print(id(var2))
var1 = 10 print(id(var1)) var2 = 12 print(id(var2))
Output: 2037008656 2037008688
- As a result above 10 digits decimal value gives the memory reference of variables var1 and var2. You may get the different value of address based on your system.
- You can also do the same for finding the address similarly for a float, string, function or an object. Because when you initialize a variable compiler seems to reserve the memory space for them on a different address value.
- Below given an example that gives the address of function sum.
def sum(var1, var2):
return var1 + var2
print("Address of funtion sum: ", id(sum))
- Furthermost above all address is Integer but you may saw many times that the memory address is written in hexadecimal format.
- Above all addresses can be converted to hexadecimal format using hex function.
- While hex() returns the hexadecimal value so it will print the address.
var1 = 2.60 print(hex(id(var1))) # print the address of var1 in hexadecimal format var2 = 3.90 print(hex(id(var2))) #print the address of var2 in hexadecimal format str1 = "Hello" print(hex(id(str1))) #print the address of str1 in hexadecimal format
var1 = 2.60 print(hex(id(var1))) # print the address of var1 in hexadecimal format var2 = 3.90 print(hex(id(var2))) #print the address of var2 in hexadecimal format str1="Hello" print(hex(id(str1))) #print the address of str1 in hexadecimal format
Output:
'0x353a208'
'0x3500588'
'0x352f180'
In this example, the memory request for the I/O buffer is handled by the C library allocator. The Python memory manager is involved only in the allocation of the bytes object returned as a result.,Raw domain: intended for allocating memory for general-purpose memory buffers where the allocation must go to the system allocator or where the allocator can operate without the GIL. The memory is requested directly to the system.,There is no guarantee that the memory returned by these allocators can be successfully cast to a Python object when intercepting the allocating functions in this domain by the methods described in the Customize Memory Allocators section.,Setup debug hooks in the Python memory allocators to detect memory errors.
PyObject * res;
char * buf = (char * ) malloc(BUFSIZ); /* for I/O */
if (buf == NULL)
return PyErr_NoMemory();
...Do some I / O operation involving buf...
res = PyBytes_FromString(buf);
free(buf); /* malloc'ed */
return res;
PyObject * res;
char * buf = (char * ) PyMem_Malloc(BUFSIZ); /* for I/O */
if (buf == NULL)
return PyErr_NoMemory();
/* ...Do some I/O operation involving buf... */
res = PyBytes_FromString(buf);
PyMem_Free(buf); /* allocated with PyMem_Malloc */
return res;
PyObject * res;
char * buf = PyMem_New(char, BUFSIZ); /* for I/O */
if (buf == NULL)
return PyErr_NoMemory();
/* ...Do some I/O operation involving buf... */
res = PyBytes_FromString(buf);
PyMem_Del(buf); /* allocated with PyMem_New */
return res;
char * buf1 = PyMem_New(char, BUFSIZ);
char * buf2 = (char * ) malloc(BUFSIZ);
char * buf3 = (char * ) PyMem_Malloc(BUFSIZ);
...
PyMem_Del(buf3); /* Wrong -- should be PyMem_Free() */
free(buf2); /* Right -- allocated via malloc() */
free(buf1); /* Fatal -- should be PyMem_Del() */