<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://www.fightorder.net/wiki/index.php?action=history&amp;feed=atom&amp;title=GlobalAI_Mono_Bindings</id>
	<title>GlobalAI Mono Bindings - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://www.fightorder.net/wiki/index.php?action=history&amp;feed=atom&amp;title=GlobalAI_Mono_Bindings"/>
	<link rel="alternate" type="text/html" href="https://www.fightorder.net/wiki/index.php?title=GlobalAI_Mono_Bindings&amp;action=history"/>
	<updated>2026-04-21T07:59:29Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.44.2</generator>
	<entry>
		<id>https://www.fightorder.net/wiki/index.php?title=GlobalAI_Mono_Bindings&amp;diff=1574&amp;oldid=prev</id>
		<title>Qrow: 1 revision imported</title>
		<link rel="alternate" type="text/html" href="https://www.fightorder.net/wiki/index.php?title=GlobalAI_Mono_Bindings&amp;diff=1574&amp;oldid=prev"/>
		<updated>2026-02-24T06:08:39Z</updated>

		<summary type="html">&lt;p&gt;1 revision imported&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 23:08, 23 February 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-notice&quot; lang=&quot;en&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(No difference)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</summary>
		<author><name>Qrow</name></author>
	</entry>
	<entry>
		<id>https://www.fightorder.net/wiki/index.php?title=GlobalAI_Mono_Bindings&amp;diff=1573&amp;oldid=prev</id>
		<title>interaidev&gt;Hughperkins: direct manageddreams.com with hughperkins.com</title>
		<link rel="alternate" type="text/html" href="https://www.fightorder.net/wiki/index.php?title=GlobalAI_Mono_Bindings&amp;diff=1573&amp;oldid=prev"/>
		<updated>2015-08-09T10:34:58Z</updated>

		<summary type="html">&lt;p&gt;direct manageddreams.com with hughperkins.com&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;= Introduction =&lt;br /&gt;
&lt;br /&gt;
Writing AIs in C# massively facilitates development, because C# runs just as fast as C++ and avoids those annoying stack/heap corruption errors.&lt;br /&gt;
&lt;br /&gt;
We have bindings for .Net Framework 1.1 and 2.0 for Windows.  It would be useful to create a set of bindings for Mono so that this could run also on any Mono-supported platform.&lt;br /&gt;
&lt;br /&gt;
Such bindings would make it possible to write portable AIs in C#, Boo (Python.Net), and any .Net language capable of being compiled into a portable ILSM class library.&lt;br /&gt;
&lt;br /&gt;
Here&amp;#039;s some thoughts on writing such bindings.&lt;br /&gt;
&lt;br /&gt;
These thoughts are taken from a fuller thread at [http://taspring.clan-sy.com/phpbb/viewtopic.php?t=7634&amp;amp;postdays=0&amp;amp;postorder=asc http://taspring.clan-sy.com/phpbb/viewtopic.php?t=7634&amp;amp;postdays=0&amp;amp;postorder=asc]&lt;br /&gt;
&lt;br /&gt;
= High-level overview =&lt;br /&gt;
&lt;br /&gt;
To create bindings for Mono, we almost certainly need a generator. The hardest part of writing a generator is parsing the input files. In the case of the Mono bindings, we can use Reflection on the existing CSAIInterfaces.dll. This could save a lot of time.&lt;br /&gt;
&lt;br /&gt;
= Download =&lt;br /&gt;
&lt;br /&gt;
Code written so far:&lt;br /&gt;
*prototyping code and generator: modified MonoEmbeddedTest at [http://hughperkins.com/csai/MonoEmbeddedTest.zip http://hughperkins.com/csai/MonoEmbeddedTest.zip]&lt;br /&gt;
*C# AI &amp;quot;Hello World&amp;quot; for Mono: [http://hughperkins.com/csai/CSharpAIMono.zip http://hughperkins.com/csai/CSharpAIMono.zip] Note that you will need to ensure that Mono-1.1.18/bin is in Spring.exe&amp;#039;s path.&lt;br /&gt;
&lt;br /&gt;
A generator has been started in the file &amp;quot;GenerateCode.cs&amp;quot; in the MonoEmbeddedTest.zip zipfile. You can build it by doing:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
csc /debug GenerateCode.cs /reference:CSAIInterfaces.dll&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using mono, you&amp;#039;d do:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mcs -debug -reference:CSAIInterfaces.dll GenerateCode.cs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Architecture =&lt;br /&gt;
&lt;br /&gt;
There are three types of classes we need to deal with:&lt;br /&gt;
*data classes, pass-by-value. This includes: Command, Float3&lt;br /&gt;
*proxied method calls from C++ to C#. This includes: IGlobalAI&lt;br /&gt;
*proxied method calls from C# to C++. This includes: IUnitDef, IAICallback&lt;br /&gt;
&lt;br /&gt;
== Pass-by-value ==&lt;br /&gt;
&lt;br /&gt;
We create a class in C++ for each pass-by-value class, with static methods &amp;quot;Marshall_MyType_to_MonoObject&amp;quot; and &amp;quot;Marshall_MonoObject_to_MyType&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The generator does this already, although it needs tweaking to cope with the double array in Command.&lt;br /&gt;
&lt;br /&gt;
Two files are created for each type: MyTypeMarshaller.cpp and MyTypeMarshaller.h&lt;br /&gt;
&lt;br /&gt;
We include the include file for the original Spring native type from MyTypeMarshaller.h, eg Float3Marshaller.h includes Float3.h.&lt;br /&gt;
&lt;br /&gt;
== Proxied method calls from C++ to C# ==&lt;br /&gt;
&lt;br /&gt;
There is only one class that this applies to, IGlobalAI.&lt;br /&gt;
&lt;br /&gt;
We create a C# class GlobalAIProxyLoader, which contains delegate definitions for each method in IGlobalAI, and which calls SetUnitCreatedHandler etc on the C++ proxy class&lt;br /&gt;
&lt;br /&gt;
We create a C++ class GlobalAIProxyCppToCs , which contains a function to receive each delegate from the C# ProxyLoader. It implements each function in IGlobalAI, redirecting to a user-provided GlobalAI C# class.&lt;br /&gt;
&lt;br /&gt;
We strip the leading &amp;quot;I&amp;quot; from the interface name to get the underlying type name.&lt;br /&gt;
&lt;br /&gt;
== Proxied method calls from C# to C++ ==&lt;br /&gt;
&lt;br /&gt;
This applies to: IUnitDef, and IAICallback.&lt;br /&gt;
&lt;br /&gt;
The native instances of these classes are always created by Spring itself, then passed back to the AI. We need to provide a C# proxy to wrap calls to a C++ proxy, which forwards the calls to the native instance.&lt;br /&gt;
&lt;br /&gt;
Two classes called MyTypeCallbackProxyCsToCpp are created, one in C# one in C++.&lt;br /&gt;
&lt;br /&gt;
The MyTypeCallbackProxyCsToCpp class in C# contains instance methods, such as SendTextMsg, which redirect to static methods, such as _SendTextMsg. The static methods are extern&amp;#039;d internal calls to methods with the same name in the MyTypeCallbackProxyCsToCpp class in C++.&lt;br /&gt;
&lt;br /&gt;
In the general case, there can be many instances of each of these proxied classes, so we create a map of reference number to instance in the C++ proxy. The reference number is an arbitrary number starting from 1.&lt;br /&gt;
&lt;br /&gt;
Each time a function on the Spring side returns a class that needs to be proxied into C#, we create a new reference number and add it to the map. The reference number is returned into the C#-side proxy, and will be used as a handle for method calls in the future.&lt;br /&gt;
&lt;br /&gt;
The C#-side proxy that called the spring function that returned the new proxied class will receive the new handle from the C++-side proxy, and create a new instance of the appropriate proxy class, passing in the new handle in the constructor. It can then pass the new proxy class instance onto the C# AI.&lt;br /&gt;
&lt;br /&gt;
The method calls from C# into C++ contain an additional first parameter, which is the reference number , which allows the C++-side proxy to select the appropriate native object and forward the call, eg to a UnitDef object. The instance methods in the C#-side proxy class will add the additional handle parameter when they call the corresponding static method.&lt;br /&gt;
&lt;br /&gt;
The method calls in the C++ proxy are static, so they can be internal-called from C#, and in a class, to avoid namespace collisions.&lt;br /&gt;
&lt;br /&gt;
= Generator main block =&lt;br /&gt;
&lt;br /&gt;
The generator main block can add each of the types to be generated into an arraylist TypesByVal, ProxiesCppToCs or ProxiesCsToCpp, as appropriate. Then when we call generate:&lt;br /&gt;
*it goes through each arraylist and generates the appropriate classes&lt;br /&gt;
*when a class undergoing generation uses one of the other classes, the generator can handle this accordingly by checking which arraylist the other classes are in&lt;br /&gt;
&lt;br /&gt;
= Use of attributes =&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s possible to add custom attributes to parameters and methods in the interface classes in CSAIInterfaces.dll . These can be read by the generator and used to tweak the generation.&lt;br /&gt;
&lt;br /&gt;
For example, we could have [MarshallAsCNullTerminatedString] vs [MarshallAsCppStdString].&lt;br /&gt;
&lt;br /&gt;
An attribute is just an empty class that derives from Attribute, eg:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[AttributeUsage(AttributeTargets.Parameter, Inherited = false, AllowMultiple = true)]&lt;br /&gt;
public class MarshallAsCNullTerminatedString: Attribute&lt;br /&gt;
{&lt;br /&gt;
   // nothing needed here, empty class&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use of attributes should probably be kept to a minimum, to avoid modifying CSAIInterfaces.dll, but the possibility exists where necessary.&lt;br /&gt;
&lt;br /&gt;
= Hand-Tweaked Code =&lt;br /&gt;
&lt;br /&gt;
It will almost certainly be necessary to add hand-tweaked code to the proxies. For example, GetMetalMap() cannot be easily guessed, because there is no info on the size of the array, and it&amp;#039;s not constant either.&lt;br /&gt;
&lt;br /&gt;
Hand-tweaked code could be added by creating a derived class, in C++, from the proxy class one wishes to tweak. This keeps generated code separate from human-written code, so it is easy to regenerate the files as the interfaces change.&lt;br /&gt;
&lt;br /&gt;
The generator will need to know the name of any derived classes so that it can use this in any &amp;quot;new&amp;quot; statements it generates for that proxy.&lt;br /&gt;
&lt;br /&gt;
= Overall =&lt;br /&gt;
&lt;br /&gt;
A plan exists that should probably work. Some code has been written. The devil is in the details.&lt;br /&gt;
&lt;br /&gt;
Writing the Mono bindings will need someone with a good knowledge of the Mono API, the Spring GlobalAI API, C, C++ and C#.&lt;br /&gt;
[[Category: AI Dev]]&lt;/div&gt;</summary>
		<author><name>interaidev&gt;Hughperkins</name></author>
	</entry>
</feed>