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引擎静态库及其调用方法的主要内容,如果未能解决你的问题,请参考以下文章
How Javascript works (Javascript工作原理) 引擎,运行时,如何在 V8 引擎中书写最优代码的 5 条小技巧