diff --git a/interpreter/cling/tools/demo/cling-demo.cpp b/interpreter/cling/tools/demo/cling-demo.cpp index 8474670d64b5ef6ce3a9eaf35ad02a38cb34fbe3..d86c3295ccb8ec618adaf418c518af8de0423aee 100644 --- a/interpreter/cling/tools/demo/cling-demo.cpp +++ b/interpreter/cling/tools/demo/cling-demo.cpp @@ -9,50 +9,72 @@ #include <cling/Interpreter/Interpreter.h> #include <cling/Interpreter/Value.h> +#include <cling/Utils/Casting.h> #include <iostream> #include <string> #include <sstream> -///\brief Pass a value from the compiled program into cling, let cling modify it -/// and return the modified value into the compiled program. -int setAndUpdate(int arg, cling::Interpreter& interp) { - int ret = arg; // The value that will be modified - // Update the value of ret by passing it to the interpreter. - std::ostringstream sstr; - sstr << "int& ref = *(int*)" << &ret << ';'; - sstr << "ref = ref * ref;"; - interp.process(sstr.str()); - return ret; +/// Definitions of declarations injected also into cling. +/// NOTE: this could also stay in a header #included here and into cling, but +/// for the sake of simplicity we just redeclare them here. +int aGlobal = 42; +static float anotherGlobal = 3.141; +float getAnotherGlobal() { return anotherGlobal; }; +void setAnotherGlobal(float val) { anotherGlobal = val; } + +///\brief Call compiled functions from the interpreter. +void useHeader(cling::Interpreter& interp) { + // We could use a header, too... + interp.declare("int aGlobal;\n" + "float getAnotherGlobal();\n" + "void setAnotherGlobal(float val);\n"); + + cling::Value res; // Will hold the result of the expression evaluation. + interp.process("aGlobal;", &res); + std::cout << "aGlobal is " << res.getAs<long long>() << '\n'; + interp.process("getAnotherGlobal();", &res); + std::cout << "getAnotherGlobal() returned " << res.getAs<float>() << '\n'; + + setAnotherGlobal(1.); // We modify the compiled value, + interp.process("getAnotherGlobal();", &res); // does the interpreter see it? + std::cout << "getAnotherGlobal() returned " << res.getAs<float>() << '\n'; + + // We modify using the interpreter, now the binary sees the new value. + interp.process("setAnotherGlobal(7.777); getAnotherGlobal();"); + std::cout << "getAnotherGlobal() returned " << getAnotherGlobal() << '\n'; } -///\brief A ridiculously complicated way of converting an int to a string. -std::unique_ptr<std::string> stringify(int value, cling::Interpreter& interp) { +///\brief Call an interpreted function using its symbol address. +void useSymbolAddress(cling::Interpreter& interp) { + // Declare a function to the interpreter. Make it extern "C" to remove + // mangling from the game. + interp.declare("extern \"C\" int plutification(int siss, int sat) " + "{ return siss * sat; }"); + void* addr = interp.getAddressOfGlobal("plutification"); + using func_t = int(int, int); + func_t* pFunc = cling::utils::VoidToFunctionPtr<func_t*>(addr); + std::cout << "7 * 8 = " << pFunc(7, 8) << '\n'; +} - // Declare the function to cling: - static const std::string codeFunc = R"CODE( -#include <string> -std::string* createAString(const char* str) { - return new std::string(str); -})CODE"; - interp.declare(codeFunc); - - // Call the function with "runtime" values: - std::ostringstream sstr; - sstr << "createAString(\"" << value << "\");"; - cling::Value res; // Will hold the result of the expression evaluation. - interp.process(sstr.str(), &res); - - // Grab the return value of `createAString()`: - std::string* resStr = static_cast<std::string*>(res.getPtr()); - return std::unique_ptr<std::string>(resStr); +///\brief Pass a pointer into cling as a string. +void usePointerLiteral(cling::Interpreter& interp) { + int res = 17; // The value that will be modified + + // Update the value of res by passing it to the interpreter. + std::ostringstream sstr; + sstr << "int& ref = *(int*)" << &res << ';'; + sstr << "ref = ref * ref;"; + interp.process(sstr.str()); + std::cout << "The square of 17 is " << res << '\n'; } int main(int argc, const char* const* argv) { - // Create the Interpreter. LLVMDIR is provided as -D during compilation. - cling::Interpreter interp(argc, argv, LLVMDIR); + // Create the Interpreter. LLVMDIR is provided as -D during compilation. + cling::Interpreter interp(argc, argv, LLVMDIR); - std::cout << "The square of 17 is " << setAndUpdate(17, interp) << '\n'; - std::cout << "Printing a string of 42: " << *stringify(42, interp) << '\n'; + useHeader(interp); + useSymbolAddress(interp); + usePointerLiteral(interp); - return 0; + return 0; }