Unable to capture standard output of process using Boost.Process - c++

Currently am using Boost.Process from the Boost sandbox, and am having issues getting it to capture my standard output properly; wondering if someone can give me a second pair of eyeballs into what I might be doing wrong.
I'm trying to take thumbnails out of RAW camera images using DCRAW (latest version), and capture them for conversion to QT QImage's.
The process launch function:
namespace bf = ::boost::filesystem;
namespace bp = ::boost::process;
QImage DCRawInterface::convertRawImage(string path) {
// commandline: dcraw -e -c <srcfile> -> piped to stdout.
if ( bf::exists( path ) ) {
std::string exec = "bin\\dcraw.exe";
std::vector<std::string> args;
args.push_back("-v");
args.push_back("-c");
args.push_back("-e");
args.push_back(path);
bp::context ctx;
ctx.stdout_behavior = bp::capture_stream();
bp::child c = bp::launch(exec, args, ctx);
bp::pistream &is = c.get_stdout();
ofstream output("C:\\temp\\testcfk.jpg");
streamcopy(is, output);
}
return (NULL);
}
inline void streamcopy(std::istream& input, std::ostream& out) {
char buffer[4096];
int i = 0;
while (!input.eof() ) {
memset(buffer, 0, sizeof(buffer));
int bytes = input.readsome(buffer, sizeof buffer);
out.write(buffer, bytes);
i++;
}
}
Invoking the converter:
DCRawInterface DcRaw;
DcRaw.convertRawImage("test/CFK_2439.NEF");
The goal is to simply verify that I can copy the input stream to an output file.
Currently, if I comment out the following line:
args.push_back("-c");
then the thumbnail is written by DCRAW to the source directory with a name of CFK_2439.thumb.jpg, which proves to me that the process is getting invoked with the right arguments. What's not happening is connecting to the output pipe properly.
FWIW: I'm performing this test on Windows XP under Eclipse 3.5/Latest MingW (GCC 4.4).
[UPDATE]
From debugging, it would appear that by the time the code reaches streamcopy, the file/pipe is already closed - bytes = input.readsome(...) is never any value other than 0.

Well I think that you need to redirect correctly the output stream. In my application something like this works :
[...]
bp::command_line cl(_commandLine);
bp::launcher l;
l.set_stdout_behavior(bp::redirect_stream);
l.set_stdin_behavior(bp::redirect_stream);
l.set_merge_out_err(true);
bp::child c = l.start(cl);
bp::pistream& is = c.get_stdout();
string result;
string line;
while (std::getline(is, line) && !_isStopped)
{
result += line;
}
c.wait();
[...]
Without the redirect the stdout will go nowhere if I remember correctly. It is a good practice to wait for the process end if you want to get the whole output.
EDIT:
I'm on Linux with perhaps an old version of boost.process. i realize that your code is similar to the snippet I gave you. The c.wait() might be the key ...
EDIT: Boost.process 0.1 :-)

If migrating to the "latest" boost.process isn't an issue (as you sure know, there are several variants for this library) ,you could use the following (http://www.highscore.de/boost/process0.5/)
file_descriptor_sink sink("stdout.txt");
execute(
run_exe("test.exe"),
bind_stdout(sink)
);

Related

Nodejs: How to start a node application from a c++ program [duplicate]

I want to use Node.js scripts in my C/C++ applications. Some people suggested me to start with v8, libev and libeio; but it means rewriting Node.js from scratch.
So, is it possible to embed Node.js into C or C++?
You should first consider whether it would be sufficient to implement your application as a C++ module for Node and then glue the main part as a Node script.
Otherwise you may wish to "re-implement Node", by taking the core code as the example and
removing the parts which you don't need (e.g. HTTP module) and then putting your components
into it. The least painful way would be to do a sub-tree merge and ripping-out the build system, then adding prefixes in the build scripts to point to the directory where it lives.
Then you can stop certain parts from being built. However Node's build system contains several parts and it may be quite a difficult job to do.
You can also try re-packaging Node with your stuff loaded by default and changing the name of the executable. However, that is just a more complex way of taking the first approach I have described, you can just install a script in /usr/bin/ which will go as:
#!/usr/bin/node
var myAppMain = require('libmyApp');
myAppMain.withConfig(filename,
function(err, cnf) {
if (err) throw err; // parser or file access error
cnf.evalMe();
});
You can use a JSlint as your parser, then grep for dangerous calls and then eval(conf_script) or just use require(config.js), though you will need to add exports.someMethod = function (...) {...}. But require() is much safer in general, however you may wish to implement a pre-processor for your config which will substitute exports.someMethod = function (...) {...} instead of your functions and will append require('OnlyCallMySafeMethods') and reject any
attempts to require('fs') or other lib which you may be afraid of letting the someone to use.
This sort of safety is just an optional thing you may wish to have, it's all up to you really.
Though I suppose you might want to do the bit with exports.someMethod = .... substitution and have one require('myAppConfigLib) added on the top so the user will just use you API plus anything they may wish to put into their script/config!
UPDATE: There is a quite useful comment on line 66 of src/node.js:
// To allow people to extend Node in different ways, this hook allows
// one to drop a file lib/_third_party_main.js into the build
// directory which will be executed instead of Node's normal loading.
Please also note that the contents of src/ are being compiled to bytecode at build time.
Embedding Node.JS is now officially supported by a Node.JS fork JXcore. Embedding docs are available from this link.
I've build something close to what I think you're looking for:
https://github.com/ZECTBynmo/tacnode
It's a library that allows node.js to be linked statically into a C++ application. It's definitely not polished, but I've used it to launch simple node scripts.
The official documentation has a page explaining how how to embed Node.js into C++. This has been around since Node 12.x.
There is a full example in the Node repo. Reproduced below for convenience:
#ifdef NDEBUG
#undef NDEBUG
#endif
#include "node.h"
#include "uv.h"
#include <assert.h>
// Note: This file is being referred to from doc/api/embedding.md, and excerpts
// from it are included in the documentation. Try to keep these in sync.
// Snapshot support is not part of the embedder API docs yet due to its
// experimental nature, although it is of course documented in node.h.
using node::CommonEnvironmentSetup;
using node::Environment;
using node::MultiIsolatePlatform;
using v8::Context;
using v8::HandleScope;
using v8::Isolate;
using v8::Locker;
using v8::MaybeLocal;
using v8::V8;
using v8::Value;
static int RunNodeInstance(MultiIsolatePlatform* platform,
const std::vector<std::string>& args,
const std::vector<std::string>& exec_args);
int main(int argc, char** argv) {
argv = uv_setup_args(argc, argv);
std::vector<std::string> args(argv, argv + argc);
std::unique_ptr<node::InitializationResult> result =
node::InitializeOncePerProcess(
args,
{node::ProcessInitializationFlags::kNoInitializeV8,
node::ProcessInitializationFlags::kNoInitializeNodeV8Platform});
for (const std::string& error : result->errors())
fprintf(stderr, "%s: %s\n", args[0].c_str(), error.c_str());
if (result->early_return() != 0) {
return result->exit_code();
}
std::unique_ptr<MultiIsolatePlatform> platform =
MultiIsolatePlatform::Create(4);
V8::InitializePlatform(platform.get());
V8::Initialize();
int ret =
RunNodeInstance(platform.get(), result->args(), result->exec_args());
V8::Dispose();
V8::DisposePlatform();
node::TearDownOncePerProcess();
return ret;
}
int RunNodeInstance(MultiIsolatePlatform* platform,
const std::vector<std::string>& args,
const std::vector<std::string>& exec_args) {
int exit_code = 0;
node::EmbedderSnapshotData::Pointer snapshot;
auto snapshot_build_mode_it =
std::find(args.begin(), args.end(), "--embedder-snapshot-create");
auto snapshot_arg_it =
std::find(args.begin(), args.end(), "--embedder-snapshot-blob");
auto snapshot_as_file_it =
std::find(args.begin(), args.end(), "--embedder-snapshot-as-file");
if (snapshot_arg_it < args.end() - 1 &&
snapshot_build_mode_it == args.end()) {
const char* filename = (snapshot_arg_it + 1)->c_str();
FILE* fp = fopen(filename, "r");
assert(fp != nullptr);
if (snapshot_as_file_it != args.end()) {
snapshot = node::EmbedderSnapshotData::FromFile(fp);
} else {
uv_fs_t req;
int statret = uv_fs_stat(nullptr, &req, filename, nullptr);
assert(statret == 0);
size_t filesize = req.statbuf.st_size;
uv_fs_req_cleanup(&req);
std::vector<char> vec(filesize);
size_t read = fread(vec.data(), filesize, 1, fp);
assert(read == 1);
snapshot = node::EmbedderSnapshotData::FromBlob(vec);
}
assert(snapshot);
int ret = fclose(fp);
assert(ret == 0);
}
std::vector<std::string> errors;
std::unique_ptr<CommonEnvironmentSetup> setup =
snapshot ? CommonEnvironmentSetup::CreateFromSnapshot(
platform, &errors, snapshot.get(), args, exec_args)
: snapshot_build_mode_it != args.end()
? CommonEnvironmentSetup::CreateForSnapshotting(
platform, &errors, args, exec_args)
: CommonEnvironmentSetup::Create(platform, &errors, args, exec_args);
if (!setup) {
for (const std::string& err : errors)
fprintf(stderr, "%s: %s\n", args[0].c_str(), err.c_str());
return 1;
}
Isolate* isolate = setup->isolate();
Environment* env = setup->env();
{
Locker locker(isolate);
Isolate::Scope isolate_scope(isolate);
HandleScope handle_scope(isolate);
Context::Scope context_scope(setup->context());
MaybeLocal<Value> loadenv_ret;
if (snapshot) {
loadenv_ret = node::LoadEnvironment(env, node::StartExecutionCallback{});
} else {
loadenv_ret = node::LoadEnvironment(
env,
// Snapshots do not support userland require()s (yet)
"if (!require('v8').startupSnapshot.isBuildingSnapshot()) {"
" const publicRequire ="
" require('module').createRequire(process.cwd() + '/');"
" globalThis.require = publicRequire;"
"} else globalThis.require = require;"
"globalThis.embedVars = { nön_ascıı: '🏳️‍🌈' };"
"require('vm').runInThisContext(process.argv[1]);");
}
if (loadenv_ret.IsEmpty()) // There has been a JS exception.
return 1;
exit_code = node::SpinEventLoop(env).FromMaybe(1);
}
if (snapshot_arg_it < args.end() - 1 &&
snapshot_build_mode_it != args.end()) {
snapshot = setup->CreateSnapshot();
assert(snapshot);
FILE* fp = fopen((snapshot_arg_it + 1)->c_str(), "w");
assert(fp != nullptr);
if (snapshot_as_file_it != args.end()) {
snapshot->ToFile(fp);
} else {
const std::vector<char> vec = snapshot->ToBlob();
size_t written = fwrite(vec.data(), vec.size(), 1, fp);
assert(written == 1);
}
int ret = fclose(fp);
assert(ret == 0);
}
node::Stop(env);
return exit_code;
}
It probably is, V8 is written in C++, node.js can run on V8, but unless you have an extremely good reason why you would run javascript through C++ you are probably much better served finding an appropriate C++ library and implementing the needed functionality directly in C++. The task of integrating scripting languages and native code is usually not trivial. E.g. V8 documentation. Qt offers a pretty decent integration between c++ and javascript and it still not trivial to move objects back and forth between script and code.
I was just checking out js-git which is made for Node.js and also depends on a few other Node.js modules.
However, the same developer wrote a tool tim-task to wrap up some common Node.js functions, most importantly require, and to pack together some Node.js modules in such a way that it should not depend on Node.js anymore. He used it to make git-web-platform, i.e. js-git packed as a JS file which can be used in browsers. The resulted packed file looks like this. This can probably also be used with minor modifications just in pure V8.
This might be useful for you. Note however that this approach will be limited.
There are many good reasons to embed node, including the ability to leverage npm.
Unfortunately JXCore is dying.
this artice gives some alternatives.
http://www.goland.org/nodeapps/

how to get linux command output string and output status in c++

I want to get a Linux command's output string as well as command output status in a C++ program. I am executing Linux commands in my application.
for example:
Command:
rmdir abcd
Command output string:
rmdir: failed to remove `abcd': No such file or directory
Command Status:
1 (Which means command has been failed)
I tried using Linux function system() which gives the output status, and function popen() which gives me output string of a command, but neither function gives me both
the output string and output status of a Linux command.
The output string is in standard output or standard error descriptor (1 or 2, respectively).
You have to redirect these streams (take a look at dup and dup2 function) to a place, where you can read them (for example - a POSIX pipe).
In C I'd do something like this:
int pd[2];
int retValue;
char buffer[MAXBUF] = {0};
pipe(pd);
dup2(pd[1],1);
retValue = system("your command");
read(pd[0], buffer, MAXBUF);
Now, you have (a part of) your output in buffer and the return code in retValue.
Alternatively, you can use a function from exec (i.e. execve) and get the return value with wait or waitpid.
Update: this will redirect only standard output. To redirect standard error, use dup2(pd[1],1).
The simplest solution is to use system, and to redirect standard out and standard error to a temporarly file, which you can delete later.
Unfortunately there's no easy and simple way in C on Linux to do this. Here's an example how to read/write stdout/stderr/stdin of child process correctly.
And when you want to receive exit code you have to use waitpid (complete example is provided on the bottom of the provided page):
endID = waitpid(childID, &status, WNOHANG|WUNTRACED);
Now you just have to join those two together :)
There's also a great free book named Advanced Linux Programming (ALP) containing detailed information about these kinds of problem available here.
Building on Piotr Zierhoffer answer above, here's a function that does just that, and also restores stdout and stderr their original state.
// Execute command <cmd>, put its output (stdout and stderr) in <output>,
// and return its status
int exec_command(string& cmd, string& output) {
// Save original stdout and stderr to enable restoring
int org_stdout = dup(1);
int org_stderr = dup(2);
int pd[2];
pipe(pd);
// Make the read-end of the pipe non blocking, so if the command being
// executed has no output the read() call won't get stuck
int flags = fcntl(pd[0], F_GETFL);
flags |= O_NONBLOCK;
if(fcntl(pd[0], F_SETFL, flags) == -1) {
throw string("fcntl() failed");
}
// Redirect stdout and stderr to the write-end of the pipe
dup2(pd[1], 1);
dup2(pd[1], 2);
int status = system(cmd.c_str());
int buf_size = 1000;
char buf[buf_size];
// Read from read-end of the pipe
long num_bytes = read(pd[0], buf, buf_size);
if(num_bytes > 0) {
output.clear();
output.append(buf, num_bytes);
}
// Restore stdout and stderr and release the org* descriptors
dup2(org_stdout, 1);
dup2(org_stderr, 2);
close(org_stdout);
close(org_stderr);
return status;
}
you can use popen system call, it will redirect output to a file and from file you can redirect output to a string. like :
char buffer[MAXBUF] = {0};
FILE *fd = popen("openssl version -v", "r");
if (NULL == fd)
{
printf("Error in popen");
return;
}
fread(buffer, MAXBUF, 1, fd);
printf("%s",buffer);
pclose(fd);
For more information read man page for popen.

Load the output of another command line program into mine

Ok suppose I have a program ( in windows a .exe file ) and when I run it, it outputs some information... now I'm writing another program ( in c++ ) and I need it to automatically run that .exe file and read the output so that it can process that information for further actions...
what should I do ?
Use popen or on windows (per comment) _popen. Basically it functions as the thing behind the | in some program | thing.
Normally I'm against posting complete code but I literally wrote this today and have it on hand, so, here you go. From what I understand C++ doesn't have a great interface that replaces popen but if you're bringing in the boost libraries or something at that layer there are solutions.
Note I use char[10] because in my application I know the output will be that short.
PopenWrapper(const std::string& command) {
fd = popen(command.c_str(), "r");
if(fd == NULL) {
throw PopenException("Failed to open command: " + command);
}
}
std::string get() {
char line[10];
fgets(line, sizeof(line), fd);
return std::string(line);
}
~PopenWrapper() {
if(fd != NULL) {
pclose(fd);
}
}

"Access violation writing location" with file.getline? (Only in release build)

getting this error in an application written in C++ (VS 2010):
Unhandled exception at 0x77648da9 in divt.exe: 0xC0000005: Access
violation writing location 0x00000014.
it points to this function in free.c:
void __cdecl _free_base (void * pBlock)
{
int retval = 0;
if (pBlock == NULL)
return;
RTCCALLBACK(_RTC_Free_hook, (pBlock, 0));
retval = HeapFree(_crtheap, 0, pBlock);
if (retval == 0) //<-----------------------right here
{
errno = _get_errno_from_oserr(GetLastError());
}
}
Via debugging I was able to determine where its actually crashing:
void MenuState::LoadContentFromFile(char* File,std::string &Content)
{
std::string strbuf;
char buffer[1028];
std::fstream file;
file.open(File,std::ios_base::in);
if(file.fail())
{
Content = ErrorTable->GetString("W0001");
return;
}
if(file.is_open())
{
while(!file.eof())
{
file.getline(buffer,128,'\n'); // <----here
strbuf = buffer;
Content += strbuf + "\n";
}
}
file.close();
strbuf.clear();
}
It crashes on file.getline(buffer,128,'\n');
I don't understand why but it's only doing it in release build (Optimizations turned off), on debug build its working fine.
Any Ideas?
I know this is an old question, but when you encounter these sorts of issues buried deep in files such as, free.c or xmemory, you may also want to double check your project configuration. Especially when the issue pertains to only certain build configurations.
For example, in MSVC check your Project Properties > Configuration Properties > C/C++ > Code Generation > Runtime Library. Make sure it consistent for all dependencies and that it is set to a Debug/Release variant depending on the current build.
I would bet that the read prior to the read crashing the application actually failed (although I'm not quite sure why it would crash). The important thing to note is that eof() is only good for determining what caused a read failure (and typically suppressing an error message). In addition, you always want to check after the read whether it was successful. Finally, I can't see any reason why you don't read an std::string directly. In summary, try to use this loop instead:
for (std::string strbuf; std::getline(file, strbuf); ) {
Content += strbuf;
}
Asked a friend for help, we came up with this Solution:
std::string strbuf;
char buffer[256] = "\0";
FILE* f = fopen(File, "rt");
while(fgets(buffer,sizeof(buffer),f) != NULL)
{
Content += buffer;
}
fclose(f);
strbuf.clear();
Works fine, still thanks for your efforts.

How to embed Node.js interpreter into C/C++?

I want to use Node.js scripts in my C/C++ applications. Some people suggested me to start with v8, libev and libeio; but it means rewriting Node.js from scratch.
So, is it possible to embed Node.js into C or C++?
You should first consider whether it would be sufficient to implement your application as a C++ module for Node and then glue the main part as a Node script.
Otherwise you may wish to "re-implement Node", by taking the core code as the example and
removing the parts which you don't need (e.g. HTTP module) and then putting your components
into it. The least painful way would be to do a sub-tree merge and ripping-out the build system, then adding prefixes in the build scripts to point to the directory where it lives.
Then you can stop certain parts from being built. However Node's build system contains several parts and it may be quite a difficult job to do.
You can also try re-packaging Node with your stuff loaded by default and changing the name of the executable. However, that is just a more complex way of taking the first approach I have described, you can just install a script in /usr/bin/ which will go as:
#!/usr/bin/node
var myAppMain = require('libmyApp');
myAppMain.withConfig(filename,
function(err, cnf) {
if (err) throw err; // parser or file access error
cnf.evalMe();
});
You can use a JSlint as your parser, then grep for dangerous calls and then eval(conf_script) or just use require(config.js), though you will need to add exports.someMethod = function (...) {...}. But require() is much safer in general, however you may wish to implement a pre-processor for your config which will substitute exports.someMethod = function (...) {...} instead of your functions and will append require('OnlyCallMySafeMethods') and reject any
attempts to require('fs') or other lib which you may be afraid of letting the someone to use.
This sort of safety is just an optional thing you may wish to have, it's all up to you really.
Though I suppose you might want to do the bit with exports.someMethod = .... substitution and have one require('myAppConfigLib) added on the top so the user will just use you API plus anything they may wish to put into their script/config!
UPDATE: There is a quite useful comment on line 66 of src/node.js:
// To allow people to extend Node in different ways, this hook allows
// one to drop a file lib/_third_party_main.js into the build
// directory which will be executed instead of Node's normal loading.
Please also note that the contents of src/ are being compiled to bytecode at build time.
Embedding Node.JS is now officially supported by a Node.JS fork JXcore. Embedding docs are available from this link.
I've build something close to what I think you're looking for:
https://github.com/ZECTBynmo/tacnode
It's a library that allows node.js to be linked statically into a C++ application. It's definitely not polished, but I've used it to launch simple node scripts.
The official documentation has a page explaining how how to embed Node.js into C++. This has been around since Node 12.x.
There is a full example in the Node repo. Reproduced below for convenience:
#ifdef NDEBUG
#undef NDEBUG
#endif
#include "node.h"
#include "uv.h"
#include <assert.h>
// Note: This file is being referred to from doc/api/embedding.md, and excerpts
// from it are included in the documentation. Try to keep these in sync.
// Snapshot support is not part of the embedder API docs yet due to its
// experimental nature, although it is of course documented in node.h.
using node::CommonEnvironmentSetup;
using node::Environment;
using node::MultiIsolatePlatform;
using v8::Context;
using v8::HandleScope;
using v8::Isolate;
using v8::Locker;
using v8::MaybeLocal;
using v8::V8;
using v8::Value;
static int RunNodeInstance(MultiIsolatePlatform* platform,
const std::vector<std::string>& args,
const std::vector<std::string>& exec_args);
int main(int argc, char** argv) {
argv = uv_setup_args(argc, argv);
std::vector<std::string> args(argv, argv + argc);
std::unique_ptr<node::InitializationResult> result =
node::InitializeOncePerProcess(
args,
{node::ProcessInitializationFlags::kNoInitializeV8,
node::ProcessInitializationFlags::kNoInitializeNodeV8Platform});
for (const std::string& error : result->errors())
fprintf(stderr, "%s: %s\n", args[0].c_str(), error.c_str());
if (result->early_return() != 0) {
return result->exit_code();
}
std::unique_ptr<MultiIsolatePlatform> platform =
MultiIsolatePlatform::Create(4);
V8::InitializePlatform(platform.get());
V8::Initialize();
int ret =
RunNodeInstance(platform.get(), result->args(), result->exec_args());
V8::Dispose();
V8::DisposePlatform();
node::TearDownOncePerProcess();
return ret;
}
int RunNodeInstance(MultiIsolatePlatform* platform,
const std::vector<std::string>& args,
const std::vector<std::string>& exec_args) {
int exit_code = 0;
node::EmbedderSnapshotData::Pointer snapshot;
auto snapshot_build_mode_it =
std::find(args.begin(), args.end(), "--embedder-snapshot-create");
auto snapshot_arg_it =
std::find(args.begin(), args.end(), "--embedder-snapshot-blob");
auto snapshot_as_file_it =
std::find(args.begin(), args.end(), "--embedder-snapshot-as-file");
if (snapshot_arg_it < args.end() - 1 &&
snapshot_build_mode_it == args.end()) {
const char* filename = (snapshot_arg_it + 1)->c_str();
FILE* fp = fopen(filename, "r");
assert(fp != nullptr);
if (snapshot_as_file_it != args.end()) {
snapshot = node::EmbedderSnapshotData::FromFile(fp);
} else {
uv_fs_t req;
int statret = uv_fs_stat(nullptr, &req, filename, nullptr);
assert(statret == 0);
size_t filesize = req.statbuf.st_size;
uv_fs_req_cleanup(&req);
std::vector<char> vec(filesize);
size_t read = fread(vec.data(), filesize, 1, fp);
assert(read == 1);
snapshot = node::EmbedderSnapshotData::FromBlob(vec);
}
assert(snapshot);
int ret = fclose(fp);
assert(ret == 0);
}
std::vector<std::string> errors;
std::unique_ptr<CommonEnvironmentSetup> setup =
snapshot ? CommonEnvironmentSetup::CreateFromSnapshot(
platform, &errors, snapshot.get(), args, exec_args)
: snapshot_build_mode_it != args.end()
? CommonEnvironmentSetup::CreateForSnapshotting(
platform, &errors, args, exec_args)
: CommonEnvironmentSetup::Create(platform, &errors, args, exec_args);
if (!setup) {
for (const std::string& err : errors)
fprintf(stderr, "%s: %s\n", args[0].c_str(), err.c_str());
return 1;
}
Isolate* isolate = setup->isolate();
Environment* env = setup->env();
{
Locker locker(isolate);
Isolate::Scope isolate_scope(isolate);
HandleScope handle_scope(isolate);
Context::Scope context_scope(setup->context());
MaybeLocal<Value> loadenv_ret;
if (snapshot) {
loadenv_ret = node::LoadEnvironment(env, node::StartExecutionCallback{});
} else {
loadenv_ret = node::LoadEnvironment(
env,
// Snapshots do not support userland require()s (yet)
"if (!require('v8').startupSnapshot.isBuildingSnapshot()) {"
" const publicRequire ="
" require('module').createRequire(process.cwd() + '/');"
" globalThis.require = publicRequire;"
"} else globalThis.require = require;"
"globalThis.embedVars = { nön_ascıı: '🏳️‍🌈' };"
"require('vm').runInThisContext(process.argv[1]);");
}
if (loadenv_ret.IsEmpty()) // There has been a JS exception.
return 1;
exit_code = node::SpinEventLoop(env).FromMaybe(1);
}
if (snapshot_arg_it < args.end() - 1 &&
snapshot_build_mode_it != args.end()) {
snapshot = setup->CreateSnapshot();
assert(snapshot);
FILE* fp = fopen((snapshot_arg_it + 1)->c_str(), "w");
assert(fp != nullptr);
if (snapshot_as_file_it != args.end()) {
snapshot->ToFile(fp);
} else {
const std::vector<char> vec = snapshot->ToBlob();
size_t written = fwrite(vec.data(), vec.size(), 1, fp);
assert(written == 1);
}
int ret = fclose(fp);
assert(ret == 0);
}
node::Stop(env);
return exit_code;
}
It probably is, V8 is written in C++, node.js can run on V8, but unless you have an extremely good reason why you would run javascript through C++ you are probably much better served finding an appropriate C++ library and implementing the needed functionality directly in C++. The task of integrating scripting languages and native code is usually not trivial. E.g. V8 documentation. Qt offers a pretty decent integration between c++ and javascript and it still not trivial to move objects back and forth between script and code.
I was just checking out js-git which is made for Node.js and also depends on a few other Node.js modules.
However, the same developer wrote a tool tim-task to wrap up some common Node.js functions, most importantly require, and to pack together some Node.js modules in such a way that it should not depend on Node.js anymore. He used it to make git-web-platform, i.e. js-git packed as a JS file which can be used in browsers. The resulted packed file looks like this. This can probably also be used with minor modifications just in pure V8.
This might be useful for you. Note however that this approach will be limited.
There are many good reasons to embed node, including the ability to leverage npm.
Unfortunately JXCore is dying.
this artice gives some alternatives.
http://www.goland.org/nodeapps/