Hello World from Javascript Core Link to heading
Continuing from my last article, today we will embed Javascript code into C++ using Apple’s Javascript Core engine that powers Safari…
Hello World from Javascript Core
Continuing from my last article, today we will embed Javascript code into C++ using Apple’s Javascript Core engine that powers Safari browser. Apple’s developer environment is unique in that they promote Objective-C and Swift, rather than conventional C or C++. The official documentation on Javascript Core is on Objective-C and Swift only, so it is not easy to find resources on how to use it on C++. Hopefully, this article will help you get started with Javascript Core on C++.
The first thing we need is Javascript Core library.
# macOS is already shipped with it
# just install command line dev tool if not already installed
xcode-select --install
# for Fedora
sudo dnf install -y webkit2gtk4.1-devel
Now, let’s write hello-world.cc file below
#include <JavaScriptCore/JavaScript.h>
#include <iostream>
#include <string>
// Function to execute JS code and return result as string
std::string execute_js_code(JSContextRef context, const std::string &code)
{
JSStringRef js_code = JSStringCreateWithUTF8CString(code.c_str());
JSValueRef result = JSEvaluateScript(context, js_code, nullptr, nullptr, 1, nullptr);
// Convert result to string
JSStringRef js_result_string = JSValueToStringCopy(context, result, nullptr);
size_t result_length = JSStringGetMaximumUTF8CStringSize(js_result_string);
char *result_cstr = new char[result_length];
JSStringGetUTF8CString(js_result_string, result_cstr, result_length);
std::string result_str(result_cstr);
// Clean up
delete[] result_cstr;
JSStringRelease(js_result_string);
JSStringRelease(js_code);
return result_str;
}
// Function to create and invoke an "add" function in JS
double call_add_function(JSContextRef context)
{
const char *js_code = R"(
function add(a, b) {
return a + b;
}
add(5, 7);
)";
JSStringRef js_code_string = JSStringCreateWithUTF8CString(js_code);
JSEvaluateScript(context, js_code_string, nullptr, nullptr, 1, nullptr);
JSStringRelease(js_code_string);
// Retrieve the result of the add function
JSValueRef result = JSEvaluateScript(context, JSStringCreateWithUTF8CString("add(5, 7);"), nullptr, nullptr, 1, nullptr);
double result_value = JSValueToNumber(context, result, nullptr);
return result_value;
}
int main()
{
// Initialize JS context
JSGlobalContextRef context = JSGlobalContextCreate(nullptr);
// Execute JS code: 'hello' + ', world'
std::string result = execute_js_code(context, "'hello' + ', world'");
std::cout << "Result of JS code execution: " << result << std::endl;
// Call add function in JS and get result
double sum = call_add_function(context);
std::cout << "Result of JS add function: " << sum << std::endl;
// Clean up
JSGlobalContextRelease(context);
return 0;
}
Finally, let’s compile
# macOS
g++ -std=c++17 -framework JavaScriptCore hello-world.cc -o hello-world
# Fedora
g++ -std=c++17 $(pkg-config --cflags --libs javascriptcoregtk-4.1) hello-world.cc -o hello-world
# run!
./hello-world
Upon success, it should print out
Result of JS code execution: hello, world
Result of JS add function: 12