使用v8 JS引擎将布尔值从C++返回到JavaScript时出现问题

gkl3eglg  于 2023-01-22  发布在  Java
关注(0)|答案(1)|浏览(154)

我正在尝试将v8静态库嵌入到我的独立C++应用程序中(macOS: Monterey 12.6,CPU:英特尔酷睿i7、Xcode:第13.1节(13 A1030 d))
1.我编写了一个简单的bash脚本来获取v8静态库:

git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
export PATH=$PWD/depot_tools:$PATH

mkdir v8
cd v8
fetch v8
cd v8

git checkout branch-heads/9.4
gclient sync

gn gen out/x64.release--args='
is_component_build = false
is_debug = false
target_cpu = "x64"
use_goma = false
v8_enable_backtrace = true
v8_enable_disassembler = true
v8_enable_object_print = true
v8_enable_verify_heap = true
dcheck_always_on = false
v8_monolithic = true
v8_use_external_startup_data = false'

ninja -C out/x64.release v8_monolith

1.将libv8_monolith.a、libv8_libplatform.a、libv8_libbase.a从out/x64.release/obj复制到我的xcode c控制台项目的文件夹,并将它们链接到该文件夹。
1.测试项目的c
部分如下所示:

#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <filesystem>

#include <v8.h>
#include <libplatform/libplatform.h>

using namespace v8;

std::string ToStdString(v8::Isolate *isolate, v8::MaybeLocal<v8::Value> valueMaybe);

bool LoadScript(const std::string& path, Isolate* _isolate, Local<Context> _context);

void LogCallback(const FunctionCallbackInfo<Value> &args);

void CreateTrue(const FunctionCallbackInfo<Value> &args) {
    v8::Isolate *isolate(args.GetIsolate());
    args.GetReturnValue().Set(v8::True(isolate));
}

void CreateFalse(const FunctionCallbackInfo<Value> &args) {
    v8::Isolate *isolate(args.GetIsolate());
    args.GetReturnValue().Set(v8::False(isolate));
}

int main(int argc, const char * argv[]) {
    std::unique_ptr<Platform> platform = v8::platform::NewDefaultPlatform();
    
    V8::InitializePlatform(platform.get());
    V8::Initialize();
    
    Isolate::CreateParams create_params;
    create_params.array_buffer_allocator = ArrayBuffer::Allocator::NewDefaultAllocator();
    Isolate* isolate = Isolate::New(create_params);
    
    Local<Context> context;
    {
        Locker l(isolate);
        Isolate::Scope isolate_scope(isolate);
        HandleScope handle_scope(isolate);
        
        Local<ObjectTemplate> global = ObjectTemplate::New(isolate);
        
        global->Set(isolate, "log", FunctionTemplate::New(isolate, LogCallback));
        
        global->Set(isolate, "cpp_CreateTrue", FunctionTemplate::New(isolate, CreateTrue));
        global->Set(isolate, "cpp_CreateFalse", FunctionTemplate::New(isolate, CreateFalse));
        
        context = Context::New(isolate,  nullptr, global);
        
        auto jsLikeBool = v8::Boolean::New(isolate, true);
        // at this point typeof this jsLikeBool equals to string, but should be equal to boolean
        if (jsLikeBool->IsBoolean()) {
            std::cout << "c++::GetBoolean jsLikeBoolean has boolean type" << std::endl;
        } else {
            std::cout << "c++::GetBoolean jsLikeBoolean DOES NOT have boolean type, but HAS: " << ToStdString(isolate, jsLikeBool->TypeOf(isolate)) << std::endl;
        }
    }
    
    if (!LoadScript(std::filesystem::current_path() / "assets" / "bools.js", isolate, context)) {
        return 1;
    }
    
    isolate->Dispose();
    V8::Dispose();
    V8::ShutdownPlatform();
    
    delete create_params.array_buffer_allocator;
    return 0;
}

1.资产/bools. js文件:

const Js_CreateTrue = () => true;
const Js_CreateFalse = () => false;

const CheckCreator = function(tag, getter, expectedType, expectedValue) {
    const value = getter();
    const valueType = typeof value;
    
    if (valueType !== expectedType) {
        log(`JS::test ${tag} failed types check, actual: ${valueType}, but expected: ${expectedType}`);
    }
        
    if (value !== expectedValue) {
        log(`JS::test ${tag} failed values check, actual: ${value}, but expected: ${expectedValue}`);
    }
}

CheckCreator("Js_CreateTrue", Js_CreateTrue, "boolean", true); // OK
CheckCreator("Js_CreateFalse", Js_CreateFalse, "boolean", false); // OK

CheckCreator("cpp_CreateTrue", cpp_CreateTrue, "boolean", true); // FAILED: gets an empty string
CheckCreator("cpp_CreateFalse", cpp_CreateFalse, "boolean", false); // causes crash in c++, actual type is `symbol`

我已经尝试了不同的标记/分支的v8源代码,没有帮助。如何摆脱这种奇怪的行为返回布尔从C++到JS?

8zzbczxx

8zzbczxx1#

我稍后会仔细研究整个问题。至于标题中的具体问题,请看下文。
v8::ReturnValue<T>有一个成员函数void Set(bool value)。将布尔值设置为返回值的正确方法是

void CreateFalse(const FunctionCallbackInfo<Value> &args) {
  args.GetReturnValue().Set(false);
}

void CreateTrue(const FunctionCallbackInfo<Value> &args) {
  args.GetReturnValue().Set(true);
}

相关问题