Facepunch.Steamworks/Generator/CodeWriter/PlatformClass.cs

209 lines
7.1 KiB
C#
Raw Normal View History

2016-10-25 12:29:35 +03:00
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Generator
{
2016-10-25 18:11:29 +03:00
public partial class CodeWriter
2016-10-25 12:29:35 +03:00
{
2016-10-25 17:57:46 +03:00
bool LargePack;
private void PlatformClass( string type, string libraryName, bool LargePack )
2016-10-25 12:29:35 +03:00
{
2016-10-25 17:57:46 +03:00
this.LargePack = LargePack;
2016-10-25 12:29:35 +03:00
StartBlock( $"internal static partial class Platform" );
2016-10-25 15:22:59 +03:00
{
2016-11-02 23:22:11 +03:00
StartBlock( $"internal class {type} : Interface" );
2016-10-25 18:37:48 +03:00
{
WriteLine( "internal IntPtr _ptr;" );
2017-02-01 15:20:47 +03:00
WriteLine( "public bool IsValid { get{ return _ptr != IntPtr.Zero; } }" );
2016-10-25 18:37:48 +03:00
WriteLine();
WriteLine( "//" );
WriteLine( "// Constructor sets pointer to native class" );
WriteLine( "//" );
2016-11-02 23:22:11 +03:00
StartBlock( $"internal {type}( IntPtr pointer )" );
2016-10-25 18:37:48 +03:00
{
WriteLine( "_ptr = pointer;" );
}
EndBlock();
WriteLine( "//" );
WriteLine( "// When shutting down clear all the internals to avoid accidental use" );
WriteLine( "//" );
StartBlock( $"public virtual void Dispose()" );
{
WriteLine( "_ptr = IntPtr.Zero;" );
}
EndBlock();
WriteLine();
foreach ( var c in def.methods.GroupBy( x => x.ClassName ) )
{
PlatformClass( c.Key, c.ToArray() );
}
StartBlock( $"internal static unsafe class Native" );
{
foreach ( var c in def.methods.GroupBy( x => x.ClassName ) )
{
InteropClass( libraryName, c.Key, c.ToArray() );
}
}
EndBlock();
}
EndBlock();
2016-10-25 12:29:35 +03:00
}
2016-10-25 15:22:59 +03:00
EndBlock();
2016-10-25 12:29:35 +03:00
}
2016-10-25 15:22:59 +03:00
private void PlatformClass( string className, SteamApiDefinition.MethodDef[] methodDef )
2016-10-25 12:29:35 +03:00
{
2016-10-25 18:37:48 +03:00
if ( ShouldIgnoreClass( className ) ) return;
2016-10-25 12:29:35 +03:00
2016-10-25 15:22:59 +03:00
LastMethodName = "";
foreach ( var m in methodDef )
{
PlatformClassMethod( className, m );
}
WriteLine();
}
private void PlatformClassMethod( string classname, SteamApiDefinition.MethodDef methodDef )
2016-10-25 12:29:35 +03:00
{
var arguments = BuildArguments( methodDef.Params );
2016-10-25 18:16:02 +03:00
var ret = new Argument( "return", methodDef.ReturnType, TypeDefs );
2016-10-25 12:29:35 +03:00
var methodName = methodDef.Name;
if ( LastMethodName == methodName )
methodName = methodName + "0";
var flatName = $"SteamAPI_{classname}_{methodName}";
2016-10-25 15:22:59 +03:00
if ( classname == "SteamApi" )
flatName = methodName;
2019-04-13 20:45:40 +03:00
var argstring = string.Join( ", ", arguments.Select( x => x.InteropParameter( true, true, true ) ) );
2016-10-25 15:22:59 +03:00
if ( argstring != "" ) argstring = $" {argstring} ";
StartBlock( $"public virtual {ret.Return()} {classname}_{methodName}({argstring})" );
2016-10-29 15:13:25 +03:00
{
2016-10-25 15:22:59 +03:00
2016-10-29 15:13:25 +03:00
// var vars = string.Join( " + \",\" + ", arguments.Where( x => !x.InteropParameter( true, true ).StartsWith( "out " ) ).Select( x => x.Name ) );
// if ( vars != "" ) vars = "\" + " + vars + " + \"";
// WriteLine( $"Console.WriteLine( \"{classname}_{methodName}( {vars} )\" );" );
2016-10-26 18:10:20 +03:00
2016-10-29 15:13:25 +03:00
if ( methodDef.NeedsSelfPointer )
{
WriteLine( $"if ( _ptr == IntPtr.Zero ) throw new System.Exception( \"{classname} _ptr is null!\" );" );
WriteLine();
}
2016-10-25 15:22:59 +03:00
2016-10-29 15:13:25 +03:00
var retcode = "";
if ( ret.NativeType != "void" )
retcode = "return ";
2016-10-25 15:22:59 +03:00
2016-10-29 15:13:25 +03:00
AfterLines = new List<string>();
2016-10-25 17:57:46 +03:00
2016-10-29 15:13:25 +03:00
foreach ( var a in arguments )
2016-10-25 17:57:46 +03:00
{
2019-04-13 20:45:40 +03:00
if ( a.InteropParameter( false, LargePack, false ).Contains( ".Pack4" ) )
2016-10-29 15:13:25 +03:00
{
2019-04-13 20:45:40 +03:00
WriteLine( $"var {a.Name}_ps = new {a.ManagedType.Trim( '*' )}.Pack4();" );
2016-10-29 15:13:25 +03:00
AfterLines.Add( $"{a.Name} = {a.Name}_ps;" );
a.Name = "ref " + a.Name + "_ps";
2016-10-25 17:57:46 +03:00
2016-10-29 15:13:25 +03:00
if ( retcode != "" )
retcode = "var ret = ";
}
2019-04-13 20:45:40 +03:00
else if ( a.InteropParameter( false, LargePack, false ).Contains( ".Pack8" ) )
{
WriteLine( $"var {a.Name}_ps = new {a.ManagedType.Trim( '*' )}.Pack8();" );
AfterLines.Add( $"{a.Name} = {a.Name}_ps;" );
a.Name = "ref " + a.Name + "_ps";
if ( retcode != "" )
retcode = "var ret = ";
}
}
2016-10-29 15:13:25 +03:00
argstring = string.Join( ", ", arguments.Select( x => x.InteropVariable( false ) ) );
if ( methodDef.NeedsSelfPointer )
argstring = "_ptr" + ( argstring.Length > 0 ? ", " : "" ) + argstring;
WriteLine( $"{retcode}Native.{flatName}({argstring});" );
2016-10-25 17:57:46 +03:00
2016-10-29 15:13:25 +03:00
WriteLines( AfterLines );
if ( retcode.StartsWith( "var" ) )
{
WriteLine( "return ret;" );
2016-10-25 17:57:46 +03:00
}
2016-10-29 15:13:25 +03:00
2016-10-25 17:57:46 +03:00
}
2016-10-29 15:13:25 +03:00
EndBlock();
LastMethodName = methodDef.Name;
}
2016-10-25 17:57:46 +03:00
2016-10-25 15:22:59 +03:00
2016-10-29 15:13:25 +03:00
private void InteropClass( string libraryName, string className, SteamApiDefinition.MethodDef[] methodDef )
{
if ( ShouldIgnoreClass( className ) ) return;
2016-10-25 15:22:59 +03:00
2016-10-29 15:13:25 +03:00
WriteLine( $"//" );
WriteLine( $"// {className} " );
WriteLine( $"//" );
2016-10-25 17:57:46 +03:00
2016-10-29 15:13:25 +03:00
LastMethodName = "";
foreach ( var m in methodDef )
2016-10-25 17:57:46 +03:00
{
2016-10-29 15:13:25 +03:00
InteropClassMethod( libraryName, className, m );
2016-10-25 17:57:46 +03:00
}
2016-10-29 15:13:25 +03:00
WriteLine();
2016-10-25 15:22:59 +03:00
}
private void InteropClassMethod( string library, string classname, SteamApiDefinition.MethodDef methodDef )
{
var arguments = BuildArguments( methodDef.Params );
2016-10-25 18:16:02 +03:00
var ret = new Argument( "return", methodDef.ReturnType, TypeDefs );
2016-10-25 15:22:59 +03:00
var methodName = methodDef.Name;
if ( LastMethodName == methodName )
methodName = methodName + "0";
var flatName = $"SteamAPI_{classname}_{methodName}";
if ( classname == "SteamApi" )
2016-10-25 12:29:35 +03:00
flatName = methodName;
2019-04-13 20:45:40 +03:00
var argstring = string.Join( ", ", arguments.Select( x => x.InteropParameter( false, LargePack, true ) ) );
2016-10-25 12:29:35 +03:00
if ( methodDef.NeedsSelfPointer )
{
argstring = "IntPtr " + classname + ( argstring.Length > 0 ? ", " : "" ) + argstring;
}
2016-10-25 15:22:59 +03:00
if ( argstring != "" ) argstring = $" {argstring} ";
2019-04-11 23:49:46 +03:00
if ( ret.Return().StartsWith( "bool " ) ) WriteLine( "[return: MarshalAs(UnmanagedType.U1)]" );
WriteLine( $"[DllImport( \"{library}\" )]" );
2016-10-26 12:32:00 +03:00
2016-10-29 15:13:25 +03:00
WriteLine( $"internal static extern {ret.Return()} {flatName}({argstring});" );
2016-10-25 12:29:35 +03:00
LastMethodName = methodDef.Name;
}
2016-10-25 15:22:59 +03:00
2016-10-25 12:29:35 +03:00
}
}