@@ -16,7 +16,7 @@ namespace Python.Runtime
1616 public static class RuntimeData
1717 {
1818
19- public readonly static Func < IFormatter > DefaultFormatterFactory = ( ) =>
19+ public readonly static Func < IFormatter ? > DefaultFormatterFactory = ( ) =>
2020 {
2121 try
2222 {
@@ -27,12 +27,12 @@ public static class RuntimeData
2727 }
2828 }
2929 catch { }
30- return new NoopFormatter ( ) ;
30+ return null ;
3131 } ;
3232
33- private static Func < IFormatter > _formatterFactory { get ; set ; } = DefaultFormatterFactory ;
33+ private static Func < IFormatter ? > _formatterFactory { get ; set ; } = DefaultFormatterFactory ;
3434
35- public static Func < IFormatter > FormatterFactory
35+ public static Func < IFormatter ? > FormatterFactory
3636 {
3737 get => _formatterFactory ;
3838 set
@@ -84,32 +84,37 @@ static void ClearCLRData ()
8484
8585 internal static void Stash ( )
8686 {
87- var runtimeStorage = new PythonNetState
88- {
89- Metatype = MetaType . SaveRuntimeData ( ) ,
90- ImportHookState = ImportHook . SaveRuntimeData ( ) ,
91- Types = TypeManager . SaveRuntimeData ( ) ,
92- Classes = ClassManager . SaveRuntimeData ( ) ,
93- SharedObjects = SaveRuntimeDataObjects ( ) ,
94- } ;
95-
96- IFormatter formatter = CreateFormatter ( ) ;
97- var ms = new MemoryStream ( ) ;
98- formatter . Serialize ( ms , runtimeStorage ) ;
99-
100- Debug . Assert ( ms . Length <= int . MaxValue ) ;
101- byte [ ] data = ms . GetBuffer ( ) ;
102- // TODO: use buffer api instead
103- IntPtr mem = PyMem_Malloc ( ms . Length + IntPtr . Size ) ;
104- Marshal . WriteIntPtr ( mem , ( IntPtr ) ms . Length ) ;
105- Marshal . Copy ( data , 0 , mem + IntPtr . Size , ( int ) ms . Length ) ;
106-
10787 ClearCLRData ( ) ;
10888
109- using NewReference capsule = PyCapsule_New ( mem , IntPtr . Zero , IntPtr . Zero ) ;
110- int res = PySys_SetObject ( "clr_data" , capsule . BorrowOrThrow ( ) ) ;
111- PythonException . ThrowIfIsNotZero ( res ) ;
112- PostStashHook ? . Invoke ( ) ;
89+ IFormatter ? formatter = CreateFormatter ( ) ;
90+
91+ if ( formatter != null )
92+ {
93+ var runtimeStorage = new PythonNetState
94+ {
95+ Metatype = MetaType . SaveRuntimeData ( ) ,
96+ ImportHookState = ImportHook . SaveRuntimeData ( ) ,
97+ Types = TypeManager . SaveRuntimeData ( ) ,
98+ Classes = ClassManager . SaveRuntimeData ( ) ,
99+ SharedObjects = SaveRuntimeDataObjects ( ) ,
100+ } ;
101+
102+ var ms = new MemoryStream ( ) ;
103+ formatter . Serialize ( ms , runtimeStorage ) ;
104+
105+ Debug . Assert ( ms . Length <= int . MaxValue ) ;
106+ byte [ ] data = ms . GetBuffer ( ) ;
107+ // TODO: use buffer api instead
108+ IntPtr mem = PyMem_Malloc ( ms . Length + IntPtr . Size ) ;
109+ Marshal . WriteIntPtr ( mem , ( IntPtr ) ms . Length ) ;
110+ Marshal . Copy ( data , 0 , mem + IntPtr . Size , ( int ) ms . Length ) ;
111+
112+ using NewReference capsule = PyCapsule_New ( mem , IntPtr . Zero , IntPtr . Zero ) ;
113+ int res = PySys_SetObject ( "clr_data" , capsule . BorrowOrThrow ( ) ) ;
114+ PythonException . ThrowIfIsNotZero ( res ) ;
115+
116+ PostStashHook ? . Invoke ( ) ;
117+ }
113118 }
114119
115120 internal static void RestoreRuntimeData ( )
@@ -126,28 +131,32 @@ internal static void RestoreRuntimeData()
126131
127132 private static void RestoreRuntimeDataImpl ( )
128133 {
129- PreRestoreHook ? . Invoke ( ) ;
130- BorrowedReference capsule = PySys_GetObject ( "clr_data" ) ;
131- if ( capsule . IsNull )
134+ IFormatter ? formatter = CreateFormatter ( ) ;
135+
136+ if ( formatter != null )
132137 {
133- return ;
134- }
135- IntPtr mem = PyCapsule_GetPointer ( capsule , IntPtr . Zero ) ;
136- int length = ( int ) Marshal . ReadIntPtr ( mem ) ;
137- byte [ ] data = new byte [ length ] ;
138- Marshal . Copy ( mem + IntPtr . Size , data , 0 , length ) ;
139- var ms = new MemoryStream ( data ) ;
140- var formatter = CreateFormatter ( ) ;
141- var storage = ( PythonNetState ) formatter . Deserialize ( ms ) ;
138+ PreRestoreHook ? . Invoke ( ) ;
139+ BorrowedReference capsule = PySys_GetObject ( "clr_data" ) ;
140+ if ( capsule . IsNull )
141+ {
142+ return ;
143+ }
144+ IntPtr mem = PyCapsule_GetPointer ( capsule , IntPtr . Zero ) ;
145+ int length = ( int ) Marshal . ReadIntPtr ( mem ) ;
146+ byte [ ] data = new byte [ length ] ;
147+ Marshal . Copy ( mem + IntPtr . Size , data , 0 , length ) ;
148+ var ms = new MemoryStream ( data ) ;
149+ var storage = ( PythonNetState ) formatter . Deserialize ( ms ) ;
142150
143- PyCLRMetaType = MetaType . RestoreRuntimeData ( storage . Metatype ) ;
151+ PyCLRMetaType = MetaType . RestoreRuntimeData ( storage . Metatype ) ;
144152
145- TypeManager . RestoreRuntimeData ( storage . Types ) ;
146- ClassManager . RestoreRuntimeData ( storage . Classes ) ;
153+ TypeManager . RestoreRuntimeData ( storage . Types ) ;
154+ ClassManager . RestoreRuntimeData ( storage . Classes ) ;
147155
148- RestoreRuntimeDataObjects ( storage . SharedObjects ) ;
156+ RestoreRuntimeDataObjects ( storage . SharedObjects ) ;
149157
150- ImportHook . RestoreRuntimeData ( storage . ImportHookState ) ;
158+ ImportHook . RestoreRuntimeData ( storage . ImportHookState ) ;
159+ }
151160 }
152161
153162 public static bool HasStashData ( )
@@ -375,9 +384,8 @@ public static MemoryStream GetSerializationData(string key)
375384 return new MemoryStream ( buffer , writable : false ) ;
376385 }
377386
378- internal static IFormatter CreateFormatter ( )
387+ internal static IFormatter ? CreateFormatter ( )
379388 {
380-
381389 if ( FormatterType != null )
382390 {
383391 return ( IFormatter ) Activator . CreateInstance ( FormatterType ) ;
0 commit comments