MALDA™ Reference Manual

The AI-First Programming Language - Version 1.0.11

30. .NET Interop

MALDA provides native support for loading and using external .NET libraries, enabling access to the vast .NET ecosystem including NuGet packages, custom class libraries, and framework APIs. This capability allows MALDA programs to leverage existing .NET code without rewriting it.

30.1 Types already in the runtime

You do not need a custom DLL for core BCL types. Pass the fully qualified name to dotnetNew or getDotNetType. Generic types use backtick arity: List`1 means List<T> with one type parameter.

var sb = dotnetNew("System.Text.StringBuilder");
sb.Append("hello");
sb.Append(" ");
sb.Append("MALDA");
print(sb.ToString());

30.2 Loading .NET Assemblies

loadAssembly(pathOrName)

Loads a .NET assembly from a file path or by assembly name.

Syntax

var asm = loadAssembly("path/to/library.dll");
var asm = loadAssembly("System.Data");  // Load by assembly name

Parameters

Returns

Behavior

Example

// Load from file path
var customLib = loadAssembly("C:\\MyLibs\\MyLibrary.dll");

// Load by assembly name (from GAC or already loaded)
var systemData = loadAssembly("System.Data");

30.3 Getting .NET Types

getDotNetType(assembly, typeName) or getDotNetType(fullTypeName)

Retrieves a .NET type from an assembly or from all loaded assemblies.

Syntax

// From a specific assembly
var type = getDotNetType(asm, "MyNamespace.MyClass");

// From any loaded assembly (searches all loaded assemblies)
var type = getDotNetType("System.Collections.Generic.List`1");

Parameters

Returns

Example

var asm = loadAssembly("MyLibrary.dll");
var myClassType = getDotNetType(asm, "MyLibrary.MyClass");

// Or search all loaded assemblies
var listType = getDotNetType("System.Collections.Generic.List`1");
Note: For generic types, use the backtick notation (e.g., List`1 for List<T>). The number after the backtick indicates the number of type parameters.

30.4 Creating .NET Objects

dotnetNew(typeOrTypeName, ...ctorArgs)

Creates a new instance of a .NET type.

Syntax

var obj = dotnetNew(typeHandle);
var obj = dotnetNew(typeHandle, arg1, arg2);  // With constructor arguments
var obj = dotnetNew("System.Text.StringBuilder");  // Direct from type name

Parameters

Returns

Example

// Using type handle
var type = getDotNetType(asm, "MyLibrary.MyClass");
var instance = dotnetNew(type);

// With constructor arguments
var instance2 = dotnetNew(type, "arg1", 42);

// Direct from type name
var sb = dotnetNew("System.Text.StringBuilder");

30.5 Using .NET Objects

Once a .NET object is created, you can:

Type Conversion

MALDA automatically converts between MALDA types and .NET types:

Example

// Load assembly and create instance
var asm = loadAssembly("C:\\path\\to\\TestLib.dll");
var fooType = getDotNetType(asm, "TestLib.Foo");
var foo = dotnetNew(fooType);

// Call instance method
var sum = foo.Add(2, 3);
print("2 + 3 = " + string(sum));

// Access and set properties
foo.Name = "from MALDA";
print("Foo.Name = " + foo.Name);

// Use a BCL type already loaded (no custom DLL)
var sb = dotnetNew("System.Text.StringBuilder");
sb.Append("item1");
sb.Append("item2");
print("Length: " + string(sb.Length));

Native callbacks

createNativeCallback(fn) wraps a MALDA function so it can be handed to .NET code that expects a delegate, for example an event handler or a callback parameter on an interop object. The argument must be a function value; anything else raises an error.

var callback = createNativeCallback((value) => {
    print("called back with " + value);
});

nativeObject.onChanged(callback);

30.6 Using NuGet Packages

To use NuGet packages in MALDA:

  1. Create a .NET Class Library that references the NuGet package
  2. Build the library to generate a .dll file
  3. Load the assembly in MALDA using loadAssembly()
  4. Use the types from the package via getDotNetType() and dotnetNew()

Example Workflow

// Load a library that uses a NuGet package (e.g., Newtonsoft.Json)
var jsonLib = loadAssembly("C:\\MyLibs\\JsonHelper.dll");
var jsonHelperType = getDotNetType(jsonLib, "JsonHelper.JsonProcessor");
var processor = dotnetNew(jsonHelperType);

// Use the library
var result = processor.ProcessJson(jsonString);

30.7 Complete Example

// Example: Using a custom .NET library
var asmPath = "C:\\MyLibraries\\MathUtils.dll";
var asm = loadAssembly(asmPath);

// Get a type from the library
var calculatorType = getDotNetType(asm, "MathUtils.Calculator");
var calc = dotnetNew(calculatorType);

// Use the calculator
var result = calc.Add(10, 20);
print("10 + 20 = " + string(result));

// Access properties
calc.Precision = 5;
print("Precision set to: " + string(calc.Precision));

30.8 Implementation Notes

30.9 Use Cases

See Also