Write a C/C++ OML Library Using the Binary-compatible Interface

The benefit of using this interface is that the objects are size-invariant. This means that the code you compile can be used with any version of Compose that supports this interface (2017.2 or later), not just the version that the header file came from. It also allows for compilation with different tools than the Compose executable uses.

Any library using this interface consists of two parts:
  • An initialization function that is called by Compose. This is how your library's functions get registered with Compose.
  • The functions themselves.
The initialization section will always have this signature:
int InitToolbox(OMLInterface* eval)

This function must be declared as extern “C” so that the name is not mangled by the compiler. It must also be exported from the DLL.

The methods of the OMLInterface class are documented in the next section.

The body of this function should be of this form:
int InitToolbox(OMLInterface* eval)
{
	eval->RegisterFunction(“myfunc”, myfunc); 
  	// myfunc needs to be forward declared
	eval->RegisterFunction(“myfunc2”, myfunc2);
	// …
	return 0;
}
Each function in the library must have this signature:
bool myfunc(OMLInterface* eval, const OMLCurrencyList* inputs, OMLCurrencyList* outputs)

Since OML is an untyped language, it is up to the writer to determine the proper C++ type for each input and handle it accordingly.

The OMLCurrencyList class and all of its subordinate classes are also documented later.

The following is a simple example that adds two scalars. If improper inputs are sent to the function (for example, the wrong number or wrong types), it will throw an error and the execution will be stopped.
bool myfunc(OMLInterface* eval, const OMLCurrencyList* inputs, OMLCurrencyList* outputs)
{
	// check proper number of inputs
if (inputs->Size() != 2)
    eval->ThrowError(“Incorrect number of inputs”);
OMLCurrency* input1 = inputs->Get(0);
OMLCurrency* input2 = inputs->Get(1);

// check proper input types
if (input1->IsScalar() && input2->IsScalar())
{
double d1 = input1->GetScalar();
double d2 = input2->GetScalar();
outputs->AddScalar(d1+d2);
}
else
{
eval->ThrowError(“Invalid input type”);
}
	return true;
}