public static void WriteHeader( TextWriter twHeader, TranslateContext translateContext, PreparedFunctions preparedFunctions, string indent) { IExtractContext extractContext = translateContext; var assemblyName = extractContext.Assembly.Name.Name; var safeSymbolName = assemblyName.Replace('.', '_').Replace('-', '_'); twHeader.WriteLine("#ifndef __MODULE_{0}__", safeSymbolName); twHeader.WriteLine("#define __MODULE_{0}__", safeSymbolName); twHeader.WriteLine(); foreach (var fileName in extractContext.EnumerateRequiredIncludeFileNames()) { twHeader.WriteLine("#include <{0}>", fileName); } var types = extractContext.Assembly.Modules .SelectMany(module => module.Types) .SelectMany(type => new[] { type }.Concat(type.NestedTypes)) // All types exclude privates .Where(type => type.IsValidDefinition() && (type.IsPublic || type.IsNestedPublic || type.IsNestedFamily || type.IsNestedFamilyOrAssembly)) .ToArray(); InternalConvertToPrototypes( twHeader, types, extractContext, preparedFunctions, method => method.IsPublic || method.IsFamily || method.IsFamilyOrAssembly, indent); twHeader.WriteLine(); twHeader.WriteLine("#endif"); }
private static void InternalConvertToPrototypes( TextWriter tw, TypeDefinition[] types, IExtractContext extractContext, PreparedFunctions preparedFunctions, Func <MethodDefinition, bool> predictMethod, string indent) { tw.WriteLine(); tw.WriteLine("#ifdef __cplusplus"); tw.WriteLine("extern \"C\" {"); tw.WriteLine("#endif"); tw.WriteLine(); tw.WriteLine("//////////////////////////////////////////////////////////////////////////////////"); tw.WriteLine("// Types:"); tw.WriteLine(); // Output prototypes. foreach (var type in types.Where(type => !type.IsEnum)) { var typeName = extractContext.GetCLanguageTypeName(type, TypeNameFlags.Dereferenced) .ManglingSymbolName(); tw.WriteLine( "typedef struct {0} {0};", typeName); } // Output value type and object reference type. foreach (var type in types) { tw.WriteLine(); InternalConvertType( tw, extractContext, type, indent); } tw.WriteLine(); tw.WriteLine("//////////////////////////////////////////////////////////////////////////////////"); tw.WriteLine("// Public static fields:"); foreach (var type in types.Where(type => !type.IsEnum)) { tw.WriteLine(); foreach (var field in type.Fields .Where(field => field.IsPublic && field.IsStatic)) { tw.WriteLine( "extern {0};", Utilities.GetStaticFieldPrototypeString(field, false, extractContext)); } } tw.WriteLine(); tw.WriteLine("//////////////////////////////////////////////////////////////////////////////////"); tw.WriteLine("// Methods:"); foreach (var type in types.Where(type => !type.IsEnum)) { var rawTypeName = type .GetFullMemberName() .ManglingSymbolName(); var typeName = extractContext .GetCLanguageTypeName(type, TypeNameFlags.Dereferenced) .ManglingSymbolName(); tw.WriteLine(); tw.WriteLine( "// {0}", type.FullName); if (!type.IsInterface) { tw.WriteLine( "extern /* internalcall */ void __{0}_IL2C_MarkHandler__({1}* this__);", rawTypeName, typeName); } tw.WriteLine( "extern /* internalcall */ void* __{0}_IL2C_RuntimeCast__({1}* this__, IL2C_RUNTIME_TYPE_DECL* type);", rawTypeName, typeName); // TODO: Support enum type methods foreach (var method in type.Methods .Where(method => (!method.IsConstructor || !method.IsStatic) && predictMethod(method))) { var preparedFunction = preparedFunctions.Functions[method]; var functionPrototype = Utilities.GetFunctionPrototypeString( GetFunctionNameByFunctionType(preparedFunction), preparedFunction.ReturnType, preparedFunction.Parameters, extractContext); tw.WriteLine( "extern {0}{1};", method.IsVirtual ? "/* virtual */ " : string.Empty, functionPrototype); } var virtualMethods = type .EnumerateOrderedOverridedMethods() .Where(predictMethod) .ToArray(); foreach (var method in virtualMethods) { var fullMethodName = type .GetFullMemberName(method, MethodNameTypes.Index) .ManglingSymbolName(); var functionParametersDeclaration = string.Join( ", ", method.GetSafeParameters() .Select((parameter, index) => (index == 0) ? string.Format( "/* {0} */ {1}", extractContext.GetCLanguageTypeName(type), parameter.Name) : string.Format( "/* {0} */ {1}", extractContext.GetCLanguageTypeName(parameter.ParameterType), parameter.Name))); tw.WriteLine( "#define {0}({1}) \\", fullMethodName, functionParametersDeclaration); var methodName = method .GetOverloadedMethodName() .ManglingSymbolName(); var functionParameters = string.Join( ", ", method.GetSafeParameters() .Select(parameter => parameter.Name)); tw.WriteLine( "{0}((this__)->vptr0__->{1}({2}))", indent, methodName, functionParameters); } } tw.WriteLine(); tw.WriteLine("#ifdef __cplusplus"); tw.WriteLine("}"); tw.WriteLine("#endif"); }
public static void WriteSourceCode( TextWriter twSource, TranslateContext translateContext, PreparedFunctions preparedFunctions, string indent, DebugInformationOptions debugInformationOption = DebugInformationOptions.Full) { IExtractContext extractContext = translateContext; foreach (var fileName in extractContext.EnumerateRequiredPrivateIncludeFileNames()) { twSource.WriteLine("#include \"{0}\"", fileName); } var assemblyName = extractContext.Assembly.Name.Name; twSource.WriteLine("#include \"{0}.h\"", assemblyName); twSource.WriteLine(); twSource.WriteLine("//////////////////////////////////////////////////////////////////////////////////"); twSource.WriteLine("// Const strings:"); twSource.WriteLine(); foreach (var kv in extractContext.ExtractConstStrings()) { var escaped = Utilities.GetEscapedCString(kv.Value); twSource.WriteLine( "IL2C_CONST_STRING({0}, L\"{1}\");", kv.Key, escaped); } var allTypes = extractContext.Assembly.Modules .SelectMany(module => module.Types) .SelectMany(type => new[] { type }.Concat(type.NestedTypes)) .Where(type => type.IsValidDefinition()) .ToArray(); // All types exclude publics and internals (for file scope prototypes) var types = allTypes .Where(type => !(type.IsPublic || type.IsNestedPublic || type.IsNestedFamily || type.IsNestedFamilyOrAssembly)) .ToArray(); InternalConvertToPrototypes( twSource, types, extractContext, preparedFunctions, method => !(method.IsPublic || method.IsFamily || method.IsFamilyOrAssembly), indent); twSource.WriteLine(); twSource.WriteLine("//////////////////////////////////////////////////////////////////////////////////"); twSource.WriteLine("// Static fields:"); foreach (var type in allTypes.Where(type => !type.IsEnum)) { twSource.WriteLine(); // All static fields foreach (var field in type.Fields .Where(field => field.IsStatic)) { twSource.WriteLine( "{0};", Utilities.GetStaticFieldPrototypeString(field, true, extractContext)); } } twSource.WriteLine(); twSource.WriteLine("//////////////////////////////////////////////////////////////////////////////////"); twSource.WriteLine("// Methods:"); foreach (var type in allTypes.Where(type => !type.IsEnum)) { twSource.WriteLine(); twSource.WriteLine("////////////////////////////////////////////////////////////"); twSource.WriteLine("// Type: {0}", type.GetFullMemberName()); // All methods and constructor exclude type initializer foreach (var method in type.Methods .Where(method => !method.IsConstructor || !method.IsStatic)) { InternalConvertFromMethod( twSource, extractContext, preparedFunctions, method, indent, debugInformationOption); } if (type.IsClass || type.IsValueType) { InternalConvertTypeHelper( twSource, extractContext, type, indent); } else if (type.IsInterface) { InternalConvertTypeHelperForInterface( twSource, type, indent); } } }
internal static void InternalConvertFromMethod( TextWriter tw, IExtractContext extractContext, PreparedFunctions preparedFunctions, MethodDefinition method, string indent, DebugInformationOptions debugInformationOption = DebugInformationOptions.None) { var methodName = method.GetFullMemberName(); var preparedFunction = preparedFunctions.Functions[method]; // Write method body switch (preparedFunction.FunctionType) { case FunctionTypes.Standard: Debug.Assert(preparedFunction.PreparedILBodies != null); InternalConvertFromFunction( tw, extractContext, preparedFunction, indent, debugInformationOption); break; case FunctionTypes.Virtual: if (preparedFunction.PreparedILBodies != null) { InternalConvertFromFunction( tw, extractContext, preparedFunction, indent, debugInformationOption); } else { InternalConvertFromAbstractFunction( tw, extractContext, preparedFunction, indent); } break; case FunctionTypes.InterfaceVirtual: // Nothing to do break; case FunctionTypes.PInvoke: var pinvokeInfo = method.PInvokeInfo; if (pinvokeInfo == null) { throw new InvalidProgramSequenceException( "Missing DllImport attribute at P/Invoke entry: Method={0}", methodName); } InternalConvertFromPInvokeFunction( tw, extractContext, preparedFunction, pinvokeInfo, indent); break; } }