Niklas R
Niklas R

Reputation: 16900

Is it possible to access an object via memory address?

In CPython, the builtin-function id(x) returns the memory address of x.
Is it possible to reverse this ?

Something like object_by_memoryadress(id(x)) == x.

Update: The reason I need this is, because I'm using a program with embedded Python. And in this program I can create so called "Nodes" that can communicate with each other, but only with integers, strings, and stuff, but I'd need to "transfer" a list between them (which is not possible the usual way).

Upvotes: 5

Views: 1325

Answers (4)

agf
agf

Reputation: 177000

If your goal is to send info between different Python processes running concurrently, check out multiprocessing or celery.

If you're just looking to be able to save / restore / pass around arbitrary Python objects, check out pickle and marshal.

The original method of doing this shared here was wrong and bad.

From @jsbueno's new answer, added here since this one sorts first:

import ctypes

def object_from_address(obj_id):
    return ctypes.cast(obj_id, ctypes.py_object).value

Upvotes: 4

jsbueno
jsbueno

Reputation: 110821

One can use ctypes to cast the id (memory address of an object) into an object:

import ctypes

def object_from_address(obj_id):
    return ctypes.cast(obj_id, ctypes.py_object).value


>>> a = [1, 2, 3]
>>> object_from_address(id(a)) is a
True

The .value property from ctypes py_object increases the refcount of the target, so the object retrieved is safe to use.

However the remark about trying this on an freed-up object (i.e. the address of a no-longer existing object) remains true: one can crash the Python runtime doing this (or eventually, resuscitate a just deleted object: good luck with that)

Upvotes: 2

Niklas R
Niklas R

Reputation: 16900

I have created a shared library that contains the following code:

#include "Python.h"
extern "C" __declspec(dllexport) PyObject* PyObjectFromAdress(long addr) {
    return (PyObject*) addr;
}

compiled it and wrapped it using ctypes:

import ctypes
dll = ctyes.cdll.thedll
object_from_id = dll.PyObjectFromAdress
object_from_id.restype = ctypes.py_object

Now you can exchange python objects through their memory adress within one python process.

l1 = []
l2 = object_from_id( id(l1) )
print l1 == l2
l1.append(9)
print l2

But be aware of already garbage collected objects ! The following code will crash the Python interpreter.

l2 = object_from_id( id([]) )
l2.append(8)

Upvotes: 1

user400055
user400055

Reputation:

I have never come across a function that could do that no. But you could keep an internal index of every object you create and store it as well as it's memory address. Then do a lookup in the table.

Upvotes: 1

Related Questions