Quasar C++ API: System.InvalidOperationException during function application
The following code snippet crashes with what looks like an unhandled exception from managed code.
#include <cassert> #include <iostream> #include "quasar_host.h" #include "quasar_dsl.h" using namespace quasar; int main(int argc, char* argv[]) { quasar::IQuasarHost* host = quasar::IQuasarHost::Create(L"cpu", true); assert(host != nullptr); QValue e(2.718281828f); Function ln(L"log()"); assert(host->FunctionExists(L"log")); QValue result = ln(e); // System.InvalidOperationException: Stack empty. host->Release(); return 0; }
The output is
Load and start the .NET runtime v4.0.30319 Initializing Quasar runtime system... Initializing Quasar compiler system... Initializing computation device... Initializing interpreter... Unhandled Exception: System.InvalidOperationException: Stack empty. at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource) at System.Collections.Generic.Stack`1.Pop() at Quasar.Interpreter.DirectInterpreter.PopReturnValues() at Quasar.Interpreter.DirectInterpreter.EvaluateIndirectFunctionCall(QValue function, QValue[] args) at Quasar.NativeInterface.FunctionCallIndirect(IntPtr functionHandle, IntPtr ptrArgsIn, Int32 nArgsIn, IntPtr ptrArgsOut, Int32 nArgsOut)
Not every function application has this issue though. Applying ‘print’ to the QValue ‘e’ works fine, for example. I tested on Windows 10, running the latest Quasar: Quasar 1.0.6128.24868 – build date 11-Oct-16 1:48:55 PM – 64-bit
The constructor for the class ‘Function’ requires the full function signature to be specified, otherwise the external C++ interface attempts to call log() without any parameters. To fix the problem, you can replace
Function ln(L"log()");
by
Function ln(L"log(??)");
It is neccessary to specify the full function signature. The error message “Stack Empty” is indeed not very clear. I will try to improve it.
You may have noted that for the print function, specifying the arguments is not required. This is because print is a function with variadic arguments. However, it would be more correct to bind to the function print as follows:
Function print(L”print(…)”);