V8引擎静态库及其调用方法

Posted 一只会铲史的猫

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了V8引擎静态库及其调用方法相关的知识,希望对你有一定的参考价值。

V8引擎静态库下载地址
由于包含了x86和x64的debug和release静态库,所以资源较大,需要耐心下载。

案例编译工具:VS2019

v8开头的即为V8引擎静态库(附送其它开源静态库libuv.lib、zlib.lib等_)

 

如何调用V8引擎
1、下载v8静态库到本地

2、配置开发环境
将上述v8的include目录配置到“附加包含目录”配置项中

根据你的开发环境配置不同版本的lib库(注意debug和release),如下:

 

3、调用代码如下,需要创建一个控制台程序

#include <iostream>
#include "v8.h"
#include "libplatform/libplatform.h"
#include <assert.h>
#include <windows.h>

#pragma comment(lib, "winmm.lib") 
#pragma comment(lib, "dbghelp.lib") 
#pragma comment(lib, "shlwapi.lib")
#pragma comment(lib, "v8_compiler.lib") 
#pragma comment(lib, "v8_libbase.lib") 
#pragma comment(lib, "v8_snapshot.lib") 
#pragma comment(lib, "v8_libplatform.lib") 
#pragma comment(lib, "v8_libsampler.lib") 
#pragma comment(lib, "v8_init.lib") 
#pragma comment(lib, "v8_initializers.lib") 
#pragma comment(lib, "v8_zlib.lib") 

#pragma comment(lib, "icudata.lib") 
#pragma comment(lib, "icutools.lib") 
#pragma comment(lib, "icuucx.lib") 
#pragma comment(lib, "icui18n.lib") 
#pragma comment(lib, "v8_base_without_compiler.lib") 
using namespace v8;
using namespace std;

//Isolate* g_isolate = nullptr;
wstring Utf8ToUnicode(const string& strSrc)
{
    /*!< 分配目标空间 */
    int iAllocSize = static_cast<int>(strSrc.size() + 10);
    WCHAR* pwszBuffer = new WCHAR[iAllocSize];
    if (NULL == pwszBuffer)
    {
        return L"";
    }
    int iCharsRet = MultiByteToWideChar(CP_UTF8, 0, strSrc.c_str(),
        static_cast<int>(strSrc.size()),
        pwszBuffer, iAllocSize);
    /*!< 成功 */
    wstring wstrRet;
    if (0 < iCharsRet)
    {
        wstrRet.assign(pwszBuffer, static_cast<size_t>(iCharsRet));
    }

    /*!< 释放内存 */
    delete[] pwszBuffer;

    return wstrRet;
}
string Utf8ToAnsi(const string& strSrc)
{
    wstring wstrTemp = Utf8ToUnicode(strSrc);

    /*!< 分配目标空间, 长度为 Ansi 编码的两倍 */
    int iAllocSize = static_cast<int>(strSrc.size() * 2 + 10);
    char* pszBuffer = new char[iAllocSize];
    if (NULL == pszBuffer)
    {
        return "";
    }
    int iCharsRet = WideCharToMultiByte(CP_ACP, 0, wstrTemp.c_str(),
        static_cast<int>(wstrTemp.size()),
        pszBuffer, iAllocSize, NULL, NULL);
    /*!< 成功 */
    string strRet;
    if (0 < iCharsRet)
    {
        strRet.assign(pszBuffer, static_cast<size_t>(iCharsRet));
    }

    /*!< 释放内存 */
    delete[] pszBuffer;

    return strRet;
}

string UnicodeToUtf8(const wstring& wstrSrc)
{
    /*!< 分配目标空间, 一个16位Unicode字符最多可以转为4个字节 */
    int iAllocSize = static_cast<int>(wstrSrc.size() * 4 + 10);
    char* pszBuffer = new char[iAllocSize];
    if (NULL == pszBuffer)
    {
        return "";
    }
    int iCharsRet = WideCharToMultiByte(CP_UTF8, 0, wstrSrc.c_str(),
        static_cast<int>(wstrSrc.size()),
        pszBuffer, iAllocSize, NULL, NULL);
    /*!< 成功 */
    string strRet;
    if (0 < iCharsRet)
    {
        strRet.assign(pszBuffer, static_cast<size_t>(iCharsRet));
    }

    /*!< 释放内存 */
    delete[] pszBuffer;

    return strRet;
}

string AnsiToUtf8(const string& strSrc)
{
    /*!< 分配目标空间, 长度为 Ansi 编码的两倍 */
    int iAllocSize = static_cast<int>(strSrc.size() * 2 + 10);
    WCHAR* pwszBuffer = new WCHAR[iAllocSize];
    if (NULL == pwszBuffer)
    {
        return "";
    }
    int iCharsRet = MultiByteToWideChar(CP_ACP, 0, strSrc.c_str(),
        static_cast<int>(strSrc.size()),
        pwszBuffer, iAllocSize);
    /*!< 成功 */
    wstring wstrTemp;
    if (0 < iCharsRet)
    {
        wstrTemp.assign(pwszBuffer, static_cast<size_t>(iCharsRet));
    }

    /*!< 释放内存 */
    delete[] pwszBuffer;

    return UnicodeToUtf8(wstrTemp);
}


Local<String> ToLocalString(Isolate* isolate, const unsigned char* pData, int iDataLen)
{
    return String::NewFromOneByte(isolate, reinterpret_cast<const uint8_t*>(pData),
        NewStringType::kNormal, iDataLen).ToLocalChecked();

}

class CPerson
{

public:
    CPerson(int iAge = 0) {
        m_iAge = iAge;
        m_pszName = "小ming";
    }
    virtual ~CPerson() {
        printf("============~CPerson()============\\n");
    };

    static void New(const FunctionCallbackInfo<Value>& args)
    {
        assert(args.IsConstructCall());

        Isolate* isolate = args.GetIsolate();

        int iAge = 0;
        if (args.Length() > 0)
            iAge = args[0].As<Int32>()->Value();

        Handle<Object> object = args.Holder();

        object->SetInternalField(0, External::New(isolate, new CPerson(iAge)));

    }

public:
    static void GetAge(const FunctionCallbackInfo<Value>& args)
    {
        // 通过参数args获取Wrap对象
        Local<Object> self = args.Holder();
        Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
        void* ptr = wrap->Value();

        CPerson* pThis = static_cast<CPerson*>(ptr);

        args.GetReturnValue().Set(pThis->m_iAge);
    }

    static void GetName(const FunctionCallbackInfo<Value>& args)
    {
        // 通过参数args获取Wrap对象
        Local<Object> self = args.Holder();
        Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
        void* ptr = wrap->Value();

        Isolate* isolate = args.GetIsolate();
        CPerson* pThis = static_cast<CPerson*>(ptr);

        string strUTF8 = AnsiToUtf8(pThis->m_pszName);
        Local<String> strName = String::NewFromUtf8(isolate, strUTF8.c_str(),
            NewStringType::kInternalized).ToLocalChecked();
        //Local<String> strName = ToLocalString(isolate, (const unsigned char*)pThis->m_pszName, strlen(pThis->m_pszName));
        args.GetReturnValue().Set(strName);
    }


public:
    int m_iAge;
    const char* m_pszName;
};


void TestFuncByJsCall(const FunctionCallbackInfo<Value>& args)
{
    Isolate* isolate = args.GetIsolate();
    int iLen = args.Length();
    if (iLen != 2)
        return;

    if (!args[0]->IsInt32())
        return;
    if (!args[1]->IsString())
        return;
    Local<Context> context = isolate->GetCurrentContext();
    int i = 0;
    args[0]->Int32Value(context).To(&i);
    String::Utf8Value str(isolate, args[1]);


    //cout << *str << "\\n";
    cout << "进入函数:" << __FUNCTION__ << "(" << i << ", \\"" << *str << "\\")" << "\\n";
    args.GetReturnValue().Set(100);
}


class PersistentToLocal
{
public:
    // If persistent.IsWeak() == false, then do not call persistent.Reset()
    // while the returned Local<T> is still in scope, it will destroy the
    // reference to the object.
    template <class TypeName>
    static inline v8::Local<TypeName> Default(v8::Isolate* isolate,
        const v8::PersistentBase<TypeName>& persistent) {
        if (persistent.IsWeak()) {
            return PersistentToLocal::Weak(isolate, persistent);
        }
        else {
            return PersistentToLocal::Strong(persistent);
        }
    }

    // Unchecked conversion from a non-weak Persistent<T> to Local<T>,
// use with care!
//
// Do not call persistent.Reset() while the returned Local<T> is still in
// scope, it will destroy the reference to the object.
    template <class TypeName>
    static inline v8::Local<TypeName> Strong(
        const v8::PersistentBase<TypeName>& persistent) {
        return *reinterpret_cast<v8::Local<TypeName>*>(
            const_cast<v8::PersistentBase<TypeName>*>(&persistent));
    }

    template <class TypeName>
    static inline v8::Local<TypeName> Weak(
        v8::Isolate* isolate,
        const v8::PersistentBase<TypeName>& persistent) {
        return v8::Local<TypeName>::New(isolate, persistent);
    }
};

int main(int argc, char* argv[])
{
    cout << argv[0] << "\\n";
    // V8初试化.
    V8::InitializeICU();

    // 加载快照文件:natives_blob.bin、snapshot_blob.bin
    V8::InitializeICUDefaultLocation(argv[0]);
    //V8::InitializeExternalStartupData(argv[0]);
//    V8::InitializeExternalStartupDataFromFile("E:/VS2019/TestV8/x64/Debug/natives_blob.bin");
//    V8::InitializeExternalStartupDataFromFile("E:/VS2019/TestV8/x64/Debug/snapshot_blob.bin");

    // 生成一个默认的platform对象
    std::unique_ptr<Platform> platform = platform::NewDefaultPlatform();
    // 初始化platform
    V8::InitializePlatform(platform.get());
    // V8的初始化
    V8::Initialize();


    std::ofstream trace_file;
    platform::InProcessStackDumping in_process_stack_dumping = // v8::platform::InProcessStackDumping::kDisabled;
        platform::InProcessStackDumping::kEnabled;
    /*
        //create v8 trace
        std::unique_ptr<v8::platform::tracing::TracingController> tracing =
            v8::base::Mutex<v8::platform::tracing::TracingController>();
        trace_file.open("v8_trace.json");
        v8::platform::tracing::TraceBuffer* trace_buffer =
            v8::platform::tracing::TraceBuffer::CreateTraceBufferRingBuffer(
                v8::platform::tracing::TraceBuffer::kRingBufferChunks,
                v8::platform::tracing::TraceWriter::CreateJSONTraceWriter(trace_file));
        tracing->Initialize(trace_buffer);

        v8::platform::tracing::TracingController* tracing_controller = tracing.get();
    */
    // 创建isolate.
    Isolate::CreateParams create_params;
    create_params.array_buffer_allocator = ArrayBuffer::Allocator::NewDefaultAllocator();
    Isolate* isolate = Isolate::New(create_params);
    {
        HandleScope scope(isolate);

        // start v8 trace
        //platform::tracing::TraceConfig* trace_config;
        //trace_config = v8::platform::tracing::TraceConfig::CreateDefaultTraceConfig();
        //tracing_controller->StartTracing(trace_config);

        Local<Context> context = Context::New(isolate);
        Context::Scope context_scope(context);

        /////////////////////////////////////////////////////
        // 一、执行JS脚本中的函数
        /////////////////////////////////////////////////////
        Local<String> source = String::NewFromUtf8(isolate,
            "function add(a, b){   var vmap = new Map(); vmap.set(\\"123\\", 1234); return vmap.get(\\"123\\");} add(1,1);",
            NewStringType::kNormal).ToLocalChecked();

        Local<Script> script = Script::Compile(context, source).ToLocalChecked();
        Local<Value> result = script->Run(context).ToLocalChecked();
        if (result->IsNumber())
            std::cout << "Test V8 jet : add(1,1) = " << Int32::Cast(*result)->Value() << "\\n";


        //const char* pszFuncName = "func";
        //Local<String> strFuncName = ToLocalString(isolate, (const unsigned char*)pszFuncName, strlen(pszFuncName));


        /////////////////////////////////////////////////////
        // 二、JS调用C函数
        /////////////////////////////////////////////////////
        //Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
        //global_template->Set(isolate, "TestFunc", FunctionTemplate::New(isolate, TestFuncByJsCall));

        context->Global()->Set(context, String::NewFromUtf8(isolate, "TestFunc").ToLocalChecked(),
            Function::New(context, TestFuncByJsCall).ToLocalChecked()).FromJust();
        Local<String> jsCall = String::NewFromUtf8(isolate,
            "TestFunc(1, \'Call From C++\');", NewStringType::kNormal).ToLocalChecked();

        Local<Script> scriptFunc;
        Local<Value> ret;
        if (Script::Compile(context, jsCall).ToLocal(&scriptFunc) &&
            scriptFunc->Run(context).ToLocal(&ret))
        {

            if (ret->IsNumber())
                std::cout << "Test V8 jet : TestFuncByJsCall = " << Int32::Cast(*ret)->Value() << "\\n";
        }

        /////////////////////////////////////////////////////
        // 三、JS调用C++类
        /////////////////////////////////////////////////////
        Local<FunctionTemplate> clsPerson = FunctionTemplate::New(isolate, CPerson::New,
            Local<Value>(), Local<Signature>(), 0,
            ConstructorBehavior::kAllow, SideEffectType::kHasSideEffect);
        const char* pszClsName = "Person";
        Local<String> clsName = ToLocalString(isolate, (const unsigned char*)pszClsName, strlen(pszClsName));
        clsPerson->SetClassName(clsName);
        Local<ObjectTemplate> objPerson = clsPerson->InstanceTemplate();
        objPerson->SetInternalFieldCount(1);
        // 1、设置CPerson类的构造函数到全局Global中
        context->Global()->Set(context, clsName, clsPerson->GetFunction(context).ToLocalChecked()).Check();

        // 2、设置GetAge方法到CPerson类中
        Local<Signature> signature = Signature::New(isolate, clsPerson);
        Local<String> NameGetAge = String::NewFromUtf8(isolate, "GetAge",
            NewStringType::kInternalized).ToLocalChecked();

        Local<FunctionTemplate> t = FunctionTemplate::New(isolate, CPerson::GetAge);
        /*Local<Value>(), signature, 0, ConstructorBehavior::kThrow,
        SideEffectType::kHasSideEffectToReceiver);*/

        clsPerson->PrototypeTemplate()->Set(NameGetAge, t);
        //clsPerson->PrototypeTemplate()->Set(isolate, "GetAge", t);
        t->SetClassName(NameGetAge);
        objPerson->Set(isolate, "GetAge", t);
        objPerson->Set(isolate, "GetName", FunctionTemplate::New(isolate, CPerson::GetName));


        //    PersistentBase<FunctionTemplate>::Strong(Person_NEW);
        // 3、执行脚本
        Local<String> jsPerson = String::NewFromUtf8(isolate,
            " var Values; "
            " function TestPerson(i){    var person = new Person(i); "
            " Values = person.GetName(); "
            //" person.GetPage = OnGetPage();"
            " person = null; return Values;     "
            "}    "
            "TestPerson(42);",
            NewStringType::kNormal).ToLocalChecked();
        // return person.GetAge();
        Local<Script> scriptClass;
        Local<Value> retClass;
        if (Script::Compile(context, jsPerson).ToLocal(&scriptClass) &&
            scriptClass->Run(context).ToLocal(&retClass))
        {
            if (retClass->IsNumber())
                std::cout << "Test V8 jet : Person = GetAge() " << Int32::Cast(*retClass)->Value() << "\\n";
            else if (retClass->IsString())
            {
                String::Utf8Value str(isolate, retClass);
                string strName = Utf8ToAnsi(*str);
                std::cout << "Test V8 jet : Person = GetName() " << strName.c_str() << "\\n";
            }
            // C++调用JS中的变量和函数
            Local<String> strValues = String::NewFromUtf8(isolate, "Values", NewStringType::kNormal).ToLocalChecked();
            Local<Value> jsValues = context->Global()->Get(context, strValues).ToLocalChecked();
            Local<Value> jsFunc = context->Global()->Get(context,
                String::NewFromUtf8(isolate, "TestPerson", NewStringType::kNormal).ToLocalChecked()).ToLocalChecked();
            if (jsValues.IsEmpty())
                printf("empty\\n");
            else if (jsValues->IsInt32())
            {
                int iAge = jsValues.As<Int32>()->Value();
                printf("C++ Call JS values: %d\\n", iAge);
            }
            else if (jsValues->IsString())
            {
                String::Utf8Value str(isolate, jsValues);
                string strName = Utf8ToAnsi(*str);
                printf("C++ Call JS values: %s\\n", strName.c_str());
            }

            if (jsFunc->IsFunction())
            {
                Local<Function> callback = jsFunc.As<Function>();
                Local<Value> recv = Undefined(isolate);
                Local<Value> ret_v;
                Local<Value> argv[1];
                argv[0] = Integer::New(isolate, 56);
                callback->Call(context, recv, 1, argv).ToLocal(&ret_v);
                if (ret_v->IsString())
                {
                    String::Utf8Value str(isolate, ret_v);
                    string strName = Utf8ToAnsi(*str);
                    printf("C++ Call JS Fuction: %s\\n", strName.c_str());
                }

            }
        } // end JS调用C++类

        /////////////////////////////////////////////////////
        // 四、JS调用dll中C函数
        /////////////////////////////////////////////////////
        HINSTANCE hV8Dll = ::LoadLibrary("v8dll.dll");
        FunctionCallback pfnCallBack = nullptr;
        if (hV8Dll && (pfnCallBack =(FunctionCallback)::GetProcAddress(hV8Dll, "fnv8dll")))
        {
            printf("=====test v8dll.dll export function=====\\n");
            context->Global()->Set(context, String::NewFromUtf8(isolate, "DllTestFunc").ToLocalChecked(),
                Function::New(context, pfnCallBack).ToLocalChecked()).FromJust();
            Local<String> jsCall = String::NewFromUtf8(isolate,
                            "DllTestFunc(1, \'Call From C++\');", 
                            NewStringType::kNormal).ToLocalChecked();

            Local<Script> scriptFunc;
            Local<Value> ret;
            if (Script::Compile(context, jsCall).ToLocal(&scriptFunc) &&
                scriptFunc->Run(context).ToLocal(&ret))
            {

                if (ret->IsNumber())
                    std::cout << "Test V8 jet : DllTestFunc = " << Int32::Cast(*ret)->Value() << "\\n";
            }
        }


    }

    char c;
    std::cin >> c;

    // 关掉v8.
    isolate->Dispose();
    V8::Dispose();
    V8::ShutdownPlatform();
    platform.reset();
}

 

以上是关于V8引擎静态库及其调用方法的主要内容,如果未能解决你的问题,请参考以下文章

浅析V8引擎,让你更懂JavaScript!

How Javascript works (Javascript工作原理) 引擎,运行时,如何在 V8 引擎中书写最优代码的 5 条小技巧

javaScript的V8引擎

v8持久setWeak回调未被调用

保姆级教程: c++游戏服务器嵌入v8 js引擎

JavaScript V8引擎