Skip to main content
GameDev.net gamedev.net

PRO Tired of ads? Read GameDev.net ad-free and help keep the community independent with GameDev Pro — $3/month.

Scripting

Scripting

benryves
benryves
Any Colour You Like · · 2 min read
1,979 3
Scripting with .NET is unbelievably easy. [grin]

I wanted to add scripting support to Brass, and have added it using .NET's excellent powers of reflection and its System.CodeDom.Compiler namespace.

The first thing I need to do is find out which language the source script is written in. I use the extension to check for this.

string ScriptFile = ...; // Name of main script file to compile.CodeDomProvider Provider = null;// Get the extension (eg "cs")string Extension = Path.GetExtension(ScriptFile).ToLowerInvariant();if (Extension.Length > 0 && Extension[0] == '.') Extension = Extension.Substring(1);// Hunt through all available compilers and dig out one with a matching extension.foreach (CompilerInfo Info in CodeDomProvider.GetAllCompilerInfo()) {	if (Info.IsCodeDomProviderTypeValid) {		CodeDomProvider TestProvider = Info.CreateProvider();		if (TestProvider.FileExtension.ToLowerInvariant() == Extension) {			Provider = TestProvider;			break;		}	}}if (Provider == null) throw new CompilerExpection(source, "Script language not supported.");

Now that we have a compiler, we just set some settings, add some references, then compile the source files:

string[] ScriptFiles = ...; // Array of source file name(s) to compile.// Compiler settings:CompilerParameters Parameters = new CompilerParameters();Parameters.GenerateExecutable = false; // Class lib, not .exeParameters.GenerateInMemory = true;// Add references:Parameters.ReferencedAssemblies.Add("System.dll");Parameters.ReferencedAssemblies.Add("Brass.exe");// Compile!CompilerResults Results = Provider.CompileAssemblyFromFile(Parameters, ScriptFiles);


And that's it! In my case I now pass any errors back up to the assembler, and exit if there were any errors:

// Errors?foreach (CompilerError Error in Results.Errors) {	Compiler.NotificationEventArgs Notification = new Compiler.NotificationEventArgs(compiler, Error.ErrorText, Error.FileName, Error.Line);	if (Error.IsWarning) {		compiler.OnWarningRaised(Notification);	} else {		compiler.OnErrorRaised(Notification);	}}// Do nothing if there were errors.if (Results.Errors.HasErrors) return;


Now the task is passed on to reflection; I go through the compiled assembly, hunt down methods and wrap them up for use as native Brass functions and/or directives.

// Grab the public classes from the script.foreach (Type T in Results.CompiledAssembly.GetExportedTypes()) {    // ...}



I've used this technique in the release of my PAL demo; a C# script file is used to encode an image to the 18x304 resolution and format required by the routine.

Discussion

Loading comments...