@@ -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,60 @@ 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
+ }
234
283
235
- if ( useMarshalMethods )
236
284
marshalMethodsCollection = MarshalMethodsCollection . FromAssemblies ( arch , assemblies . Values . ToList ( ) , resolver , Log ) ;
285
+ marshalMethodsCollection . AddSpecialCaseMethods ( ) ;
286
+ }
287
+
288
+ var state = new NativeCodeGenState ( arch , tdCache , resolver , allJavaTypes , javaTypesForJCW , marshalMethodsCollection ) ;
289
+
290
+ if ( useMarshalMethods ) {
291
+ var info = new ManagedMarshalMethodsLookupInfo ( Log ) ;
292
+
293
+ foreach ( var kvp in marshalMethodsCollection . MarshalMethods )
294
+ foreach ( var method in kvp . Value )
295
+ info . AddNativeCallbackWrapper ( method . NativeCallback ) ;
296
+
297
+ state . ManagedMarshalMethodsLookupInfo = info ;
298
+ }
237
299
238
- return ( true , new NativeCodeGenState ( arch , tdCache , resolver , allJavaTypes , javaTypesForJCW , marshalMethodsCollection ) ) ;
300
+ return ( true , state , stateObject ) ;
239
301
}
240
302
241
303
( List < TypeDefinition > allJavaTypes , List < TypeDefinition > javaTypesForJCW ) ScanForJavaTypes ( XAAssemblyResolver res , TypeDefinitionCache cache , Dictionary < string , ITaskItem > assemblies , Dictionary < string , ITaskItem > userAssemblies , bool useMarshalMethods )
0 commit comments