How do I save an instance of a custom class to a .blend file?
I've been dealing with a similar problem; I have a number of instances of custom Python classes defined during the execution of a custom Python script, and I'd like to be able to maintain (or restore) references to these custom class instances even after the script has finished running, or after Blender has been closed and then later re-opened.
The simplest solution I've found so far is to use the standard Python pickling module, extending the base pickler and unpickler classes to build picklers that know how to recover 'persistent external references' to Blender objects. This isn't as nice as saving the custom class instances as part of the .blend file itself, but does allow me to save the custom class instances whenever my script is run, and to later unpickle them with correct Blender object references. With a few minor changes to the script, this lets me optionally run the script multiple times while actively modifying the same class instances, without losing them in between script invocations.
To illustrate what I mean, here's a simple example of a custom class instance with active Blender object references I'd like to be able to pickle to a file and re-load later:
&gt;&gt;&gt; class example():
...     def __init__(self, obj, ex_dict):
...         self.obj = obj
...         self.ex_dict = ex_dict
&gt;&gt;&gt; ex = example(bpy.context.object, {1:2, &quot;dog&quot;:&quot;cat&quot;}

By default, I can't pickle this:
&gt;&gt;&gt; with open(&quot;example.pickle&quot;, 'wb') as f:
...     pickle.dump(ex, f, pickle.HIGHEST_PROTOCOL)
...     
Traceback (most recent call last):
  File &quot;&lt;blender_console&gt;&quot;, line 2, in &lt;module&gt;
TypeError: can't pickle Object objects

But I can write a custom pickler, unpickler that know how to store and revive references to 'persistent external (Blender) objects', like so:
&gt;&gt;&gt; class BpyPickler(pickle.Pickler):
...     def persistent_id(self, obj):
...         if isinstance(obj, bpy.types.Object):
...             return (&quot;BpyObj&quot;, obj.name)
...         else:
...             return None
...             
&gt;&gt;&gt; class BpyUnpickler(pickle.Unpickler):
...     def __init__(self, f):
...         super().__init__(f)
...     def persistent_load(self, pid):
...         type_tag, type_id = pid
...         if type_tag == &quot;BpyObj&quot;:
...             return bpy.data.objects[type_id]
...         else:
...             raise pickle.UnpicklingError(f&quot;unsupported obj with persistent id {pid}&quot;)

And with these changes, I can now successfully pickle and unpickle-with-restored-bpy-obj-references my class:
&gt;&gt;&gt; with open(&quot;example3.pickle&quot;, 'wb') as f:
...     BpyPickler(f).dump(ex)
...     
&gt;&gt;&gt; with open(&quot;example3.pickle&quot;, 'rb') as f:
...     ex3 = BpyUnpickler(f).load()
...     
&gt;&gt;&gt; ex3
&lt;__main__.example object at 0x000001BD0C4013C8&gt;

&gt;&gt;&gt; ex3.obj
bpy.data.objects['floorPanelSharpCorner.007']

&gt;&gt;&gt; ex3.ex_dict
{1: 2, 'dog': 'cat'}