如何在v8 C ++中创建异步回调函数(不使用Node JS)?

时间:2018-01-11 16:50:19

标签: c++ v8

我试图在v8 js引擎中创建一个回调,但这不起作用。也就是说,我无法保存该功能以便以后调用它。看看谷歌,但有一切都是关于如何通过Node JS来做的。如何在干净的V8上没有Node JS? PS:在回调下我会输入:

function Func()
{
    print("YEEES");
}
cl.register(Func);

试图像这样保存(但这不起作用):

v8::Persistent<v8::Function> *savedFunc = NULL;
Locker locker(_isolate);
HandleScope scope(_isolate);
Handle<Function> args1 = Handle<Function>::Cast(args[0]);

savedFunc = new v8::Persistent<v8::Function>();
savedFunc->Reset(_isolate, args1);

我需要这个来描述程序对JS的操作。也就是说,例如,添加一个用鼠标按下按钮或移动的事件,并从C ++调用它。 (这就是我为游戏所做的事情)

对不起我的英语。 谷歌翻译

修改

感谢pinepain的回答

解决问题的方法: CPP

//callback test
//Рабочий пример каллбека. В коде много лишнего
//Working example of callback. Here a lot of things you can delete
#include <include/v8.h>

#include <include/libplatform/libplatform.h>

#include <stdlib.h>
#include <string.h>

#include <map>
#include <process.h>
#include <string>

using std::map;
using std::pair;
using std::string;

using v8::Context;
using v8::EscapableHandleScope;
using v8::External;
using v8::Function;
using v8::FunctionTemplate;
using v8::Global;
using v8::HandleScope;
using v8::Isolate;
using v8::Local;
using v8::MaybeLocal;
using v8::Name;
using v8::NamedPropertyHandlerConfiguration;
using v8::NewStringType;
using v8::Object;
using v8::ObjectTemplate;
using v8::PropertyCallbackInfo;
using v8::Script;
using v8::String;
using v8::TryCatch;
using v8::Value;

class HttpRequestProcessor {
public:
    virtual ~HttpRequestProcessor() { }
    virtual bool Initialize(map<string, string>* options,map<string, string>* output) = 0;
    virtual bool Process() = 0;
    static void Log(const char* event);
};

class JsHttpRequestProcessor : public HttpRequestProcessor {
public:
    JsHttpRequestProcessor(Isolate* isolate, Local<String> script)
        : isolate_(isolate), script_(script) {}
    virtual ~JsHttpRequestProcessor();
    virtual bool Initialize(map<string, string>* opts,      map<string, string>* output);
    virtual bool Process();

private:
    bool ExecuteScript(Local<String> script);
    Isolate* GetIsolate() { return isolate_; }

    Isolate* isolate_;
    Local<String> script_;
    Global<Context> context_;
    Global<Function> process_;
};
Global<Function> process_f;

static void LogCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() < 1) return;
    Isolate* isolate = args.GetIsolate();
    HandleScope scope(isolate);
    Local<Value> arg = args[0];
    String::Utf8Value value(isolate, arg);
    HttpRequestProcessor::Log(*value);
}

static void Callback(const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() < 1) return;
    Isolate* isolate = args.GetIsolate();
    HandleScope scope(isolate);
    Local<Value> arg = args[0];
    if (!arg->IsFunction()) {
        return;
    }
    Local<Function> process_fun = Local<Function>::Cast(arg);
    process_f.Reset(isolate, process_fun);
}

bool JsHttpRequestProcessor::Initialize(map<string, string>* opts,
    map<string, string>* output) {
    HandleScope handle_scope(GetIsolate());

    Local<ObjectTemplate> global = ObjectTemplate::New(GetIsolate());
    global->Set(String::NewFromUtf8(GetIsolate(), "log", NewStringType::kNormal)
        .ToLocalChecked(),
        FunctionTemplate::New(GetIsolate(), LogCallback));
    global->Set(String::NewFromUtf8(GetIsolate(), "callback", NewStringType::kNormal)
        .ToLocalChecked(),
        FunctionTemplate::New(GetIsolate(), Callback));

    v8::Local<v8::Context> context = Context::New(GetIsolate(), NULL, global);
    context_.Reset(GetIsolate(), context);

    Context::Scope context_scope(context);

    if (!ExecuteScript(script_))
        return false;

    Local<String> process_name =
        String::NewFromUtf8(GetIsolate(), "Process", NewStringType::kNormal)
        .ToLocalChecked();
    Local<Value> process_val;
    if (!context->Global()->Get(context, process_name).ToLocal(&process_val) ||
        !process_val->IsFunction()) {
        return false;
    }
    Local<Function> process_fun = Local<Function>::Cast(process_val);
    process_.Reset(GetIsolate(), process_fun);
    return true;
}


bool JsHttpRequestProcessor::ExecuteScript(Local<String> script) {
    HandleScope handle_scope(GetIsolate());

    TryCatch try_catch(GetIsolate());

    Local<Context> context(GetIsolate()->GetCurrentContext());

    Local<Script> compiled_script;
    if (!Script::Compile(context, script).ToLocal(&compiled_script)) {
        String::Utf8Value error(GetIsolate(), try_catch.Exception());
        Log(*error);
        return false;
    }

    Local<Value> result;
    if (!compiled_script->Run(context).ToLocal(&result)) {
        String::Utf8Value error(GetIsolate(), try_catch.Exception());
        Log(*error);
        return false;
    }
    return true;
}


bool JsHttpRequestProcessor::Process() {
    HandleScope handle_scope(GetIsolate());

    v8::Local<v8::Context> context =
        v8::Local<v8::Context>::New(GetIsolate(), context_);
    Context::Scope context_scope(context);

    TryCatch try_catch(GetIsolate());
    v8::Local<v8::Function> process =
        v8::Local<v8::Function>::New(GetIsolate(), process_f);
    Local<Value> result;
    if (!process->Call(context, context->Global(), 0, {}).ToLocal(&result)) {
        String::Utf8Value error(GetIsolate(), try_catch.Exception());
        Log(*error);
        return false;
    }
    return true;
}


JsHttpRequestProcessor::~JsHttpRequestProcessor() {
    context_.Reset();
    process_.Reset();
}

void HttpRequestProcessor::Log(const char* event) {
    printf("Logged: %s\n", event);
}


void ParseOptions(int argc,
    char* argv[],
    map<string, string>* options,
    string* file) {
    for (int i = 1; i < argc; i++) {
        string arg = argv[i];
        size_t index = arg.find('=', 0);
        if (index == string::npos) {
            *file = arg;
        }
        else {
            string key = arg.substr(0, index);
            string value = arg.substr(index + 1);
            (*options)[key] = value;
        }
    }
}


// Reads a file into a v8 string.
MaybeLocal<String> ReadFile(Isolate* isolate, const string& name) {
    FILE* file = fopen(name.c_str(), "rb");
    if (file == NULL) return MaybeLocal<String>();

    fseek(file, 0, SEEK_END);
    size_t size = ftell(file);
    rewind(file);

    char* chars = new char[size + 1];
    chars[size] = '\0';
    for (size_t i = 0; i < size;) {
        i += fread(&chars[i], 1, size - i, file);
        if (ferror(file)) {
            fclose(file);
            return MaybeLocal<String>();
        }
    }
    fclose(file);
    MaybeLocal<String> result = String::NewFromUtf8(
        isolate, chars, NewStringType::kNormal, static_cast<int>(size));
    delete[] chars;
    return result;
}
JsHttpRequestProcessor* proc;
void cproc() 
{
    proc->Process();
}

int main(int argc, char* argv[]) {
    v8::V8::InitializeICUDefaultLocation(argv[0]);
    v8::V8::InitializeExternalStartupData(argv[0]);
    std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
    v8::V8::InitializePlatform(platform.get());
    v8::V8::Initialize();
    map<string, string> options;
    string file;
    ParseOptions(argc, argv, &options, &file);
    if (file.empty()) {
        fprintf(stderr, "No script was specified.\n");
        return 1;
    }
    Isolate::CreateParams create_params;
    create_params.array_buffer_allocator =
        v8::ArrayBuffer::Allocator::NewDefaultAllocator();
    Isolate* isolate = Isolate::New(create_params);
    Isolate::Scope isolate_scope(isolate);
    HandleScope scope(isolate);
    Local<String> source;
    if (!ReadFile(isolate, file).ToLocal(&source)) {
        fprintf(stderr, "Error reading '%s'.\n", file.c_str());
        return 1;
    }
    proc = new JsHttpRequestProcessor(isolate, source);
    map<string, string> output;
    if (!proc->Initialize(&options, &output)) {
        fprintf(stderr, "Error initializing processor.\n");
        return 1;
    }
    while (true)
        {
            cproc();
        }
    }

JS

function proc()
{
    log("Print: " + a);
    a++;
}
callback(proc);

原始代码(github):process.cc

0 个答案:

没有答案