@@ -155,6 +155,7 @@ void Run (bool useMarshalMethods)
155
155
156
156
// Now that "never" never happened, we can proceed knowing that at least the assembly sets are the same for each architecture
157
157
var nativeCodeGenStates = new ConcurrentDictionary < AndroidTargetArch , NativeCodeGenState > ( ) ;
158
+ var nativeCodeGenStateObjects = new ConcurrentDictionary < AndroidTargetArch , NativeCodeGenStateObject > ( ) ;
158
159
NativeCodeGenState ? templateCodeGenState = null ;
159
160
160
161
var firstArch = allAssembliesPerArch . First ( ) . Key ;
@@ -169,7 +170,7 @@ void Run (bool useMarshalMethods)
169
170
// Pick the "first" one as the one to generate Java code for
170
171
var generateJavaCode = arch == firstArch ;
171
172
172
- ( bool success , NativeCodeGenState ? state ) = GenerateJavaSourcesAndMaybeClassifyMarshalMethods ( arch , archAssemblies , MaybeGetArchAssemblies ( userAssembliesPerArch , arch ) , useMarshalMethods , generateJavaCode ) ;
173
+ ( bool success , NativeCodeGenState ? state , NativeCodeGenStateObject ? stateObject ) = GenerateJavaSourcesAndMaybeClassifyMarshalMethods ( arch , archAssemblies , MaybeGetArchAssemblies ( userAssembliesPerArch , arch ) , useMarshalMethods , generateJavaCode ) ;
173
174
174
175
if ( ! success ) {
175
176
generateSucceeded = false ;
@@ -181,6 +182,7 @@ void Run (bool useMarshalMethods)
181
182
}
182
183
183
184
nativeCodeGenStates . TryAdd ( arch , state ) ;
185
+ nativeCodeGenStateObjects . TryAdd ( arch , stateObject ) ;
184
186
} ) ;
185
187
186
188
// If we hit an error generating the Java code, we should bail out now
@@ -198,6 +200,21 @@ void Run (bool useMarshalMethods)
198
200
// Save NativeCodeGenState for later tasks
199
201
Log . LogDebugMessage ( $ "Saving { nameof ( NativeCodeGenState ) } to { nameof ( NativeCodeGenStateRegisterTaskKey ) } ") ;
200
202
BuildEngine4 . RegisterTaskObjectAssemblyLocal ( MonoAndroidHelper . GetProjectBuildSpecificTaskObjectKey ( NativeCodeGenStateRegisterTaskKey , WorkingDirectory , IntermediateOutputDirectory ) , nativeCodeGenStates , RegisteredTaskObjectLifetime . Build ) ;
203
+
204
+ // If we still need the NativeCodeGenState in the <GenerateNativeMarshalMethodSources> task because we're using marshal methods,
205
+ // we're going to transfer it to a new object that doesn't require holding open Cecil AssemblyDefinitions.
206
+ if ( useMarshalMethods ) {
207
+ //var nativeCodeGenStateObject = MarshalMethodCecilAdapter.GetNativeCodeGenStateCollection (Log, nativeCodeGenStates);
208
+ var nativeCodeGenStateCollection = new NativeCodeGenStateCollection ( ) ;
209
+
210
+ foreach ( var kvp in nativeCodeGenStateObjects ) {
211
+ nativeCodeGenStateCollection . States . Add ( kvp . Key , kvp . Value ) ;
212
+ Log . LogDebugMessage ( $ "Added NativeCodeGenStateObject for arch: { kvp . Key } , containing { kvp . Value . MarshalMethods . Count } marshal methods") ;
213
+ }
214
+
215
+ Log . LogDebugMessage ( $ "Saving { nameof ( NativeCodeGenStateObject ) } to { nameof ( GenerateJavaStubs . NativeCodeGenStateObjectRegisterTaskKey ) } ") ;
216
+ BuildEngine4 . RegisterTaskObjectAssemblyLocal ( MonoAndroidHelper . GetProjectBuildSpecificTaskObjectKey ( GenerateJavaStubs . NativeCodeGenStateObjectRegisterTaskKey , WorkingDirectory , IntermediateOutputDirectory ) , nativeCodeGenStateCollection , RegisteredTaskObjectLifetime . Build ) ;
217
+ }
201
218
}
202
219
203
220
internal static Dictionary < string , ITaskItem > MaybeGetArchAssemblies ( Dictionary < AndroidTargetArch , Dictionary < string , ITaskItem > > dict , AndroidTargetArch arch )
@@ -209,7 +226,7 @@ internal static Dictionary<string, ITaskItem> MaybeGetArchAssemblies (Dictionary
209
226
return archDict ;
210
227
}
211
228
212
- ( bool success , NativeCodeGenState ? stubsState ) GenerateJavaSourcesAndMaybeClassifyMarshalMethods ( AndroidTargetArch arch , Dictionary < string , ITaskItem > assemblies , Dictionary < string , ITaskItem > userAssemblies , bool useMarshalMethods , bool generateJavaCode )
229
+ ( bool success , NativeCodeGenState ? stubsState , NativeCodeGenStateObject ? stateObject ) GenerateJavaSourcesAndMaybeClassifyMarshalMethods ( AndroidTargetArch arch , Dictionary < string , ITaskItem > assemblies , Dictionary < string , ITaskItem > userAssemblies , bool useMarshalMethods , bool generateJavaCode )
213
230
{
214
231
XAAssemblyResolver resolver = MakeResolver ( useMarshalMethods , arch , assemblies ) ;
215
232
var tdCache = new TypeDefinitionCache ( ) ;
@@ -227,15 +244,62 @@ internal static Dictionary<string, ITaskItem> MaybeGetArchAssemblies (Dictionary
227
244
}
228
245
229
246
if ( ! success ) {
230
- return ( false , null ) ;
247
+ return ( false , null , null ) ;
231
248
}
232
249
233
250
MarshalMethodsCollection ? marshalMethodsCollection = null ;
251
+ NativeCodeGenStateObject ? stateObject = null ;
252
+
253
+ if ( useMarshalMethods ) {
254
+ stateObject = new NativeCodeGenStateObject ( ) ;
255
+
256
+ foreach ( var assembly in assemblies . Values ) {
257
+ var marshalMethodXmlFile = MarshalMethodsXmlFile . GetMarshalMethodsXmlFilePath ( assembly . ItemSpec ) ;
258
+
259
+ if ( ! File . Exists ( marshalMethodXmlFile ) )
260
+ continue ;
261
+
262
+ var xml = MarshalMethodsXmlFile . Import ( marshalMethodXmlFile ) ;
263
+
264
+ if ( xml is null || xml ? . Value . MarshalMethods . Count == 0 ) {
265
+ Log . LogDebugMessage ( $ "'{ marshalMethodXmlFile } ' is empty, skipping.") ;
266
+ continue ;
267
+ }
268
+
269
+ foreach ( var kvp in xml . Value . Value . MarshalMethods ) {
270
+ if ( ! stateObject . MarshalMethods . TryGetValue ( kvp . Key , out var methods ) ) {
271
+ methods = new List < MarshalMethodEntryObject > ( ) ;
272
+ stateObject . MarshalMethods . Add ( kvp . Key , methods ) ;
273
+ }
274
+
275
+ foreach ( var method in kvp . Value ) {
276
+ // We don't need to add the special case method multiple times
277
+ if ( methods . Count > 0 && method . IsSpecial )
278
+ continue ;
279
+ methods . Add ( method ) ;
280
+ }
281
+ }
282
+ }
283
+
284
+ //marshalMethodsCollection = MarshalMethodsCollection.FromAssemblies (arch, assemblies.Values.ToList (), resolver, Log);
285
+ //marshalMethodsCollection.AddSpecialCaseMethods ();
286
+
287
+ marshalMethodsCollection = new EmptyMarshalMethodsCollection ( ) ;
288
+ }
289
+
290
+ var state = new NativeCodeGenState ( arch , tdCache , resolver , allJavaTypes , javaTypesForJCW , marshalMethodsCollection ) ;
234
291
235
- if ( useMarshalMethods )
236
- marshalMethodsCollection = MarshalMethodsCollection . FromAssemblies ( arch , assemblies . Values . ToList ( ) , resolver , Log ) ;
292
+ // if (useMarshalMethods) {
293
+ // var info = new ManagedMarshalMethodsLookupInfo ( Log);
237
294
238
- return ( true , new NativeCodeGenState ( arch , tdCache , resolver , allJavaTypes , javaTypesForJCW , marshalMethodsCollection ) ) ;
295
+ // foreach (var kvp in marshalMethodsCollection.MarshalMethods)
296
+ // foreach (var method in kvp.Value)
297
+ // info.AddNativeCallbackWrapper (method.NativeCallback);
298
+
299
+ // state.ManagedMarshalMethodsLookupInfo = info;
300
+ //}
301
+
302
+ return ( true , state , stateObject ) ;
239
303
}
240
304
241
305
( List < TypeDefinition > allJavaTypes , List < TypeDefinition > javaTypesForJCW ) ScanForJavaTypes ( XAAssemblyResolver res , TypeDefinitionCache cache , Dictionary < string , ITaskItem > assemblies , Dictionary < string , ITaskItem > userAssemblies , bool useMarshalMethods )
@@ -343,4 +407,43 @@ void CompareLists (string name, List<string> list1, List<string> list2)
343
407
Log . LogDebugMessage ( $ "No differences") ;
344
408
}
345
409
}
410
+
411
+ class EmptyMarshalMethodsCollection : MarshalMethodsCollection
412
+ {
413
+ public override HashSet < AssemblyDefinition > AssembliesWithMarshalMethods => throw new NotSupportedException ( ) ;
414
+
415
+ /// <summary>
416
+ /// Marshal methods that have already been rewritten as LLVM marshal methods.
417
+ /// </summary>
418
+ public override IDictionary < string , IList < ConvertedMarshalMethodEntry > > ConvertedMarshalMethods => throw new NotSupportedException ( ) ;
419
+
420
+ /// <summary>
421
+ /// Marshal methods that cannot be rewritten and must be registered dynamically.
422
+ /// </summary>
423
+ public override List < DynamicallyRegisteredMarshalMethodEntry > DynamicallyRegisteredMarshalMethods => throw new NotSupportedException ( ) ;
424
+
425
+ /// <summary>
426
+ /// Marshal methods that can be rewritten as LLVM marshal methods.
427
+ /// </summary>
428
+ public override IDictionary < string , IList < MarshalMethodEntry > > MarshalMethods => throw new NotSupportedException ( ) ;
429
+
430
+ public EmptyMarshalMethodsCollection ( )
431
+ {
432
+ }
433
+
434
+ public override void AddSpecialCaseMethods ( )
435
+ {
436
+ throw new NotImplementedException ( ) ;
437
+ }
438
+
439
+ public override bool ShouldBeDynamicallyRegistered ( TypeDefinition topType , MethodDefinition registeredMethod , MethodDefinition implementedMethod , CustomAttribute registerAttribute )
440
+ {
441
+ throw new NotImplementedException ( ) ;
442
+ }
443
+
444
+ public override bool TypeHasDynamicallyRegisteredMethods ( TypeDefinition type )
445
+ {
446
+ throw new NotImplementedException ( ) ;
447
+ }
448
+ }
346
449
}
0 commit comments