IL2CPU
IL2CPU copied to clipboard
Use ref locals to get class fields in Plugs
When there is the need to access a field of a class you have to add a ref variable to one of its plug method and use the attribute "FieldAccess" this could be easily become ugly when you need to access a lot of fields:
public static void Ctor(StreamWriter aThis, string path, bool append, Encoding encoding, int bufferSize,
[FieldAccess(Name = "System.IO.Stream System.IO.StreamWriter._stream")] ref Stream _stream,
[FieldAccess(Name = "System.Int32 System.IO.StreamWriter._charPos")] ref int _charPos,
[FieldAccess(Name = "System.Char[] System.IO.StreamWriter._charBuffer")] ref int _charLen,
[FieldAccess(Name = "System.Char[] System.IO.StreamWriter._charBuffer")] ref char[] _charBuffer,
[FieldAccess(Name = "System.Byte[] System.IO.StreamWriter._byteBuffer")] ref byte[] _byteBuffer,
[FieldAccess(Name = "System.Char[] System.IO.TextWriter.CoreNewLine")] ref char[] CoreNewLine
)
I've had two constructors to plug (one that take a String representing a File Path and an other in which you pass a Stream already created) and so the ideal solution would have been to use an utility function to initialize all the field but I will have to pass all the ref variables and their value to it that well defeat the purpose of it a lot!
My idea is leaving the attribute version for the old code (or replace it if we are so brave) and to use ref locals introduced in C# 7 to resolve this problem so the Init() would become:
private static void Init(Stream stream, bool append, CosmosEncoding encoding, int bufferSize, bool shouldLeaveOpen)
{
ref Stream _stream = ref GetFieldAccess("System.IO.Stream System.IO.StreamWriter._stream");
ref int _charPos = ref GetFieldAccess("System.Int32 System.IO.StreamWriter._charPos");
ref char[] _charBuffer = ref GetFieldAccess("System.Char[] System.IO.StreamWriter._charBuffer");
ref byte[] _byteBuffer = ref GetFieldAccess("System.Byte[] System.IO.StreamWriter._byteBuffer");
ref char[] CoreNewLine = ref GetFieldAccess("System.Char[] System.IO.TextWriter.CoreNewLine");
_stream = stream;
[...]
}
GetFieldAccess should have these prototypes:
ref object GetFieldAccess(String FieldName);
ref object[] GetFieldAccess(String FieldName);
unsafe ref void *GetFieldAccess(String FieldName); // Not working in C# 7.0 should be added in future releases
Another way make easier to access to field is to add the possibility to plug a field explicitly without the needed of a plug method.
Taking this example again one could write:
public static class StreamWriterImpl
{
[PlugField name="System.IO.Stream System.IO.StreamWriter._stream"] Stream stream;
With a little of compiler "trickery" we will obtain that: stream
wouldn't change
it wouldn't even be compiled if we want when loading or storing that field, the compiler would load or store _stream
instead.