globalaicinterfacegenerator.cs

来自「这是整套横扫千军3D版游戏的源码」· CS 代码 · 共 354 行

CS
354
字号
using System;
using System.Collections;
using System.Reflection;
using System.IO;

using CSharpAI;

// The goal of this generator is to generator the bulk of the function calls for AICallback, UnitDef and MoveData.  It will also create a .def file for them
//
// You can define which types are targeted for generation in the Go() method right at the bottom of the file
//
// You may also want to mess with CsTypeToCppTypeString , but you probably wont have to; be careful with this function
//
// For each type we will generate the following files:
// <typename>_generated.cpp
// <typename>_generated.h
//
// The code in generated.cpp will look something like:
// AICALLBACK_API int UnitDef_get_id( const UnitDef *self )
// {
//     return self->id;
// }
//
// There is always an additional argument called self which is an opaque pointer.  An opaque pointer means the AI knows it's a struct, but doesnt
// know what is in the struct
//
// The code in generated.h will look something like:
// AICALLBACK_API int UnitDef_get_id( const UnitDef *self );

class GenerateCode
{
    byte[] ReadFile( String filename )
    {
        FileStream fs = new FileStream( filename, FileMode.Open );
        BinaryReader br = new BinaryReader( fs );
        Byte[] bytes = br.ReadBytes( (int)fs.Length );
        br.Close();
        return bytes;
    }
    
    // returns array of the types of the parameters of the method specified by methodinfo
    public static Type[] GetParameterTypes( MethodBase methodbase )
    {
        ParameterInfo[] parameterinfos = methodbase.GetParameters();
        Type[] paramtypes = new Type[ parameterinfos.GetUpperBound(0) + 1 ];
        for( int i = 0; i < parameterinfos.GetUpperBound(0) + 1; i ++ )
        {
            paramtypes[i] = parameterinfos[i].ParameterType;
        }
        return paramtypes;
    }

    
    // returns public class members having the attribute attributetype
    // if attributetype is null, returns all public members
    public static MemberInfo[] GetMembersForAttribute( Type objecttype )
    {
        ArrayList members = new ArrayList();
        foreach( MemberInfo memberinfo in objecttype.GetMembers() )
        {
    //        if( attributetype == null || HasAttribute( memberinfo, attributetype ) )
       //     {
                members.Add( memberinfo );
       //     }
        }
        return (MemberInfo[])members.ToArray( typeof( MemberInfo ) );
    }
    
    class ExceptionCsTypeNotHandled : Exception
    {
        public ExceptionCsTypeNotHandled( string msg ) : base( msg )
        {
        }
    }
    
    string CsTypeToCppTypeString( Type CsType, bool IsReturnType )
    {
        if( CsType == typeof( int ) )
        {
            return "int";
        }
        if( CsType == typeof( double ) )
        {
            return "float";
        }
        if( CsType == typeof( string ) )
        {
            //return "const char *";
            if( IsReturnType )
            {
                return "const char *";
            }
            return "char *";
            // return "std::string";
        }
        if( CsType == typeof( bool ) )
        {
            return "bool";
        }
        if( CsType == typeof( IUnitDef ) )
        {
            return "const UnitDef *";
        }
        if( CsType == typeof( void ) )
        {
            return "void";
        }
        
        throw new ExceptionCsTypeNotHandled("type " + CsType.ToString() + " not handled");
    }
    
    void Analyze( Type targettype )
    {
        Console.WriteLine( "analyzing " + targettype.ToString() + " ... " );
        foreach( MemberInfo memberinfo in targettype.GetMembers() )
        {
            //Console.WriteLine( memberinfo.MemberType.ToString() + " " + memberinfo.Name );
            if( memberinfo.MemberType == MemberTypes.Field )
            {
                //Console.WriteLine( memberinfo.Name );
                FieldInfo fi = targettype.GetField( memberinfo.Name );
                Console.WriteLine( "Field: " + memberinfo.Name + " " + fi.FieldType + " isliteral " + fi.IsLiteral.ToString() );
            }
            else if( memberinfo.MemberType == MemberTypes.Property )
            {
                //Console.WriteLine( memberinfo.Name );
                PropertyInfo pi = targettype.GetProperty( memberinfo.Name );
                Console.WriteLine( "Property: " + pi.PropertyType + " " + memberinfo.Name );
            }
            else if( memberinfo.MemberType == MemberTypes.Method )
            {
                Console.WriteLine( memberinfo.MemberType.ToString() + " " + memberinfo.Name );
                MethodBase methodbase = memberinfo as MethodBase;
                MethodInfo methodinfo = memberinfo as MethodInfo;
                Console.WriteLine( "   returntype " + methodinfo.ReturnType.ToString() );
                ParameterInfo[] parameterinfos = methodbase.GetParameters();
                for( int i = 0; i < parameterinfos.GetUpperBound(0) + 1; i ++ )
                {
                    Console.WriteLine( "   parameter " + parameterinfos[i].ParameterType + " " + parameterinfos[i].Name );
                }
                //Console.WriteLine( memberinfo.Name );
                //MethodInfo mi = targettype.GetMethod( memberinfo.Name );
                //Console.WriteLine( memberinfo.Name );
            }
        }
    }
    
    void WriteHeaderComments( StreamWriter sw )
    {
        sw.WriteLine( "// *** This is a generated file; if you want to change it, please change CSAIInterfaces.dll, which is the reference" );
        sw.WriteLine( "// " );
        sw.WriteLine( "// This file was generated by ABICCodeGenerator, by Hugh Perkins hughperkins@gmail.com http://manageddreams.com" );
        sw.WriteLine( "// " );
    }
    
    string GetDeclarationString( Type targettype, string basetypename, MemberInfo memberinfo )
    {
        if( memberinfo.MemberType == MemberTypes.Field )
        {
            FieldInfo fi = targettype.GetField( memberinfo.Name );
            if( !fi.IsLiteral ) // ignore constants
            {
              //  headerfile.WriteLine( "   " + "mono_field_get_value( monoobject, mono_class_get_field_from_name (thisclass, \"" + memberinfo.Name + "\"), &(" + nativeobjectname + "->" + memberinfo.Name + " ) );" );
            }
        }
        else if( memberinfo.MemberType == MemberTypes.Property )
        {
            PropertyInfo pi = targettype.GetProperty( memberinfo.Name );
            string thismethoddeclaration = "AICALLBACK_API ";
            thismethoddeclaration += CsTypeToCppTypeString( pi.PropertyType, true ) + " " + basetypename + "_get_" + memberinfo.Name;
            thismethoddeclaration += "( ";
            thismethoddeclaration += "const ";
            thismethoddeclaration += basetypename + " *self )";
            return thismethoddeclaration;
        }
        else if( memberinfo.MemberType == MemberTypes.Method )
        {
            if( memberinfo.Name.IndexOf( "get_" ) != 0 ) // ignore property accessors
            {
                MethodBase methodbase = memberinfo as MethodBase;
                MethodInfo methodinfo = memberinfo as MethodInfo;
                ParameterInfo[] parameterinfos = methodbase.GetParameters();
                string thismethoddeclaration = "AICALLBACK_API ";
                thismethoddeclaration += CsTypeToCppTypeString( methodinfo.ReturnType, true ) + " ";
                thismethoddeclaration += basetypename + "_" + methodinfo.Name;
                thismethoddeclaration += "( ";
                thismethoddeclaration += "const ";
                thismethoddeclaration += basetypename + " *self";
                for( int i = 0; i < parameterinfos.GetUpperBound(0) + 1; i++ )
                {
                    if( i < parameterinfos.GetUpperBound(0) + 1 )
                    {
                        thismethoddeclaration += ", ";
                    }
                    thismethoddeclaration += CsTypeToCppTypeString( parameterinfos[i].ParameterType, false ) + " " + parameterinfos[i].Name;
                }
                thismethoddeclaration += " )";
                return thismethoddeclaration;
            }
        }
        
        return "";
    }
    
    bool ArrayContains( string[] array, string value )
    {
        foreach( string thisvalue in array )
        {
            if( thisvalue == value )
            {
                return true;
            }
        }
        return false;
    }
    
    void GenerateFor( Type targettype, string basetypename, string[]methodstoignore )
    {
        string[] splittargettypestring = targettype.ToString().Split(".".ToCharArray() );
        string namespacename = "";
        if( splittargettypestring.GetUpperBound(0) + 1 > 1 )
        {
            namespacename = splittargettypestring[ 0 ];
        }
        string typename = splittargettypestring[ splittargettypestring.GetUpperBound(0) ];
        //string basetypename = typename.Substring(1); // remove leading "I"
        string basefilename = typename + "_generated";

        StreamWriter headerfile = new StreamWriter( basefilename + ".h", false );        
        WriteHeaderComments( headerfile );    
        
// target code to generate for header:
// AICALLBACK_API int UnitDef_get_id( const UnitDef *self );
        
// target code to generate for cpp:
// AICALLBACK_API int UnitDef_get_id( const UnitDef *self )
// {
//     return self->id;
// }
        StreamWriter cppfile = new StreamWriter( basefilename + ".gpp", false );        
        WriteHeaderComments( cppfile );    
        foreach( MemberInfo memberinfo in targettype.GetMembers() )
        {
            if( !ArrayContains( methodstoignore, memberinfo.Name ) )
            {
                try
                {
                    string declarationstring = GetDeclarationString( targettype, basetypename, memberinfo );
                    if( declarationstring != "" )
                    {
                        // first we generate the string, throwing exceptions as appropriate
                        // then we write them to file if they worked out ok
                        // this needs to be atomic, so that we always have both header declaration + cpp definition, or neither
                        string cppdeclaration = declarationstring + "\n";
                        cppdeclaration += "{\n";
                        string defmethodname = "";
                        if( memberinfo.MemberType == MemberTypes.Property )
                        {
                            PropertyInfo pi = targettype.GetProperty( memberinfo.Name );
                            defmethodname = basetypename + "_get_" + memberinfo.Name;
                            cppdeclaration += "   return ( ( " + basetypename + " *) self)->" + memberinfo.Name; // we can assume a property wont return void
                            if( pi.PropertyType == typeof( string ) )
                            {
                                cppdeclaration += ".c_str()";
                            }
                            cppdeclaration += ";\n";
                        }
                        else if( memberinfo.MemberType == MemberTypes.Method )
                        {
                            defmethodname = basetypename + "_" + memberinfo.Name;
                            MethodInfo methodinfo = memberinfo as MethodInfo;
                            if( methodinfo.ReturnType != typeof( void ) )
                            {
                                cppdeclaration += "   return ( ( " + basetypename + " *)self )->" + memberinfo.Name + "( ";
                            }
                            else
                            {
                                cppdeclaration += "   ( ( " + basetypename + " *)self )->" + memberinfo.Name + "( ";
                            }
                            
                            ParameterInfo[] parameterinfos = methodinfo.GetParameters();
                            for( int i = 0; i < parameterinfos.GetUpperBound(0) + 1; i++ )
                            {
                                if( i > 0 )
                                {
                                    cppdeclaration += ", ";
                                }
                                cppdeclaration += parameterinfos[i].Name;
                            }
                                
                            cppdeclaration += "  );\n";                        
                        }
                        cppdeclaration += "}\n";
                        cppdeclaration += "\n";
                        
                        headerfile.WriteLine( declarationstring + ";" );
                        cppfile.WriteLine( cppdeclaration );
                        //deffile.WriteLine( nextdefnum + "\t" + defmethodname );
                        deffile.WriteLine( defmethodname );
                    }
                }
                catch( ExceptionCsTypeNotHandled e )
                {
                    Console.WriteLine("Ignoring " + memberinfo.MemberType.ToString() + " " + typename + "." + memberinfo.Name + " " + e.Message );
                }
                catch( Exception e )
                {
                    Console.WriteLine( e.ToString() );
                }
            }
        }
        
        headerfile.Close();
        cppfile.Close();
    }
    
    string deffilename;
    //int nextdefnum;
    
    StreamWriter deffile;
    
    public void Go()
    {
        // analyze gives you information on a type; useful during development
         //Analyze( typeof( IAICallback ) );
         // Analyze( typeof( IUnitDef ) );
         //Analyze( typeof( IMoveData ) );
        
        deffilename = "def_generated.def";
        //nextdefnum = 1; // can change this to begin def numbering at different number
        
        deffile = new StreamWriter( deffilename, false );
        deffile.WriteLine("EXPORTS");
        
        // Parameters: typename in CSAIInterfaces, native Spring typename, methods to ignore
        GenerateFor( typeof( IAICallback ), "IAICallback", new string[]{
            "UnitIsBusy", "IsGamePaused","GetUnitDefByTypeId" } );
        GenerateFor( typeof( IUnitDef ), "UnitDef", new string[]{"GetNumBuildOptions","GetBuildOption"} );
        GenerateFor( typeof( IMoveData ), "MoveData", new string[]{} );
        GenerateFor( typeof( IFeatureDef ), "FeatureDef", new string[]{} );
            
        deffile.Close();
    }
}
    
class entrypont
{
    public static void Main(string[] args)
    {
        new GenerateCode().Go();
    }
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?