External API calls

Functions in DLLs/assemblies that target Microsoft's .NET Framework can be called using EXTERN DOTNET XJEase functions. Each EXTERN DOTNET function defines a single external API function, that may then be called like any other XJEase function. The definition must always include the list of parameters to pass in (like a normal XJEase function definition), the binary to load, and the target function to call. The parameters being passed in must match the function being called otherwise an error will be raised at compile time. At run time external binary files are loaded the first time one is called, and are not unloaded until the end of the run.

As with other XJEase function definitions, they may be forward-declared using the DECLARE keyword.

Each assembly may optionally define an XJEaseRuntimeInterface static class that allows some interaction with the runtime.

Syntax

EXTERN DOTNET name ( { type inParameter { WIDTH width }, ... } ) ( { type outParameter { WIDTH width }, ... } )
    API_BINARY := binary;
    API_TARGET := target;
END;

Parameters

name
A STRING specifying the name of the function as it will be referenced from XJEase. The name must follow the same rules as other XJEase functions and must not conflict with any other function names.
type
The XJEase type of a parameter (see Function parameters below).
inParameter
The name of an input parameter (see Function parameters below).
outParameter
The name of an output parameter (see Function parameters below).
binary
A STRING containing the filename of the assembly that the function is in (see Binary below).
target
A STRING containing the full qualified name of the .NET Framework method to call (see Target below).

Function parameters

External API parameters must be from the following types: bool, sbyte, byte, byte[], short, ushort, int, uint, long, ulong, enum, string. See the section below about handling signed integer types

Function parameters must match the target function parameters, with XJEase STRING parameters matching any .NET strings and XJEase INT parameters matching all other types. The names of the parameters do not need to match the target function names: all matching is done purely on the parameters' types.

XJEase doesn't support passing input parameters by reference, but it supports multiple output parameters, which are passed by reference. Any out or ref parameters are therefore mapped to XJEase output parameters, rather than inputs. The first XJEase output parameter is the function's return value, if it has one, followed by any out and ref parameters in the order they appear.

This C# function has a return value and a ref and an out parameter:

public static int Function(string stringParam, ref int refParam, out string outParam, int finalParam)

The return value becomes the first XJEase output parameter and the two ref and out parameters become additional output parameters in the same order that they originally appear:

EXTERN DOTNET Function(STRING stringParam, INT finalParam)(INT ret, INT refParam, STRING outParam)

If the parameters do not match any target functions, the compiler will report an error.

Binary

The location may be given relative to the xje file it is defined in, or as an absolute path. Be aware that adding files with absolute paths is not recommended if the project is going to be copied or packed and then reloaded on other machines.

If the file is not found there will be a compile time error.

The binary must only be loaded from one location otherwise there will be a compile time error.

If there is a file with the same name as the binary in the XJTAG program executable folder, an error will be raised at compile time.

When a project is packed, all assemblies referenced will be automatically included in the XJPack file the same way as .xje files.

Target

The name of the function to call including any namespace and class.

If the target is not found there will be a compile time error.

If there are multiple overloads that cannot be distinguished (only varying by XJEase style INTs) there will be a compile time error.

Signed integer parameters

XJEase INT values are always unsigned, but XJEase supports calling of APIs which use signed integers. Signed integer types (sbyte, short, int, long) will be treated within XJEase as unsigned values of the appropriate length (8 bits for sbyte through to 64 bits for long), and thus if a function returns an sbyte value of -2, XJEase will print that value as 254. Likewise 254 can be passed in to a method using an sbyte parameter and the called function will receive the value -2.

Example Code

// C# API dll
namespace XJTAG
{
    public static class Class1
    {
        public static void Function1(int a);
        public static void Function1(string a);
        public static void Function2(out int a);
        public static int Function3();
        public static int Function4(int a, int b, ref int c, out int d);
    }
}
// XJEase External API Headers
EXTERN DOTNET ExternalFunction1(INT in)()
  API_BINARY := "External dlls\\ExternalWrapper.dll";
  API_TARGET := "XJTAG.Class1.Function1";
END;

EXTERN DOTNET ExternalFunction1String(STRING in)()
  API_BINARY := "External dlls\\ExternalWrapper.dll";
  API_TARGET := "XJTAG.Class1.Function1";
END;

EXTERN DOTNET ExternalFunction2()(INT out)
  API_BINARY := "External dlls\\ExternalWrapper.dll";
  API_TARGET := "XJTAG.Class1.Function2";
END;

EXTERN DOTNET ExternalFunction3()(INT ret)
  API_BINARY := "External dlls\\ExternalWrapper.dll";
  API_TARGET := "XJTAG.Class1.Function3";
END;

EXTERN DOTNET ExternalFunction4(INT in1, INT in2)(INT ret, INT ref, INT out)
  API_BINARY := "External dlls\\ExternalWrapper.dll";
  API_TARGET := "XJTAG.Class1.Function4";
END;

// XJEase Test Code
GLOBAL ExternalTest()(INT result)
  INT in1 := 10;
  INT in2 := 20;
  INT ret, ref, out;
  STRING inString := "hello";

  // Call external dll functions
  ExternalFunction1(in1)();
  ExternalFunction1String(inString)();
  ExternalFunction2()(out1);
  result := ExternalFunction3();
  ExternalFunction4(in1, in2)(ret, ref, out);
END;