使用v8的共享库与静态链接的v8不兼容

Shared library using v8 is incompatible with statically linked v8?

本文关键字:v8 链接 不兼容 静态 共享 使用      更新时间:2023-10-16

下面是真正问题的一些背景故事:

我正在做一个项目,使用Chromium Embedded Framework(CEF)和v8为嵌入式浏览器中运行的JavaScript提供原生C++函数绑定。

具体来说,我要做的是在加载任何页面或上下文之前构造一个v8::ObjectTemplate,然后在CEF的OnContextCreated回调中,创建该模板的新实例,并将其作为全局window对象的属性添加。

问题是CEF的API封装了v8上下文和值,为您提供了一个指向接口的(智能)指针,从而完全隐藏了它使用v8的事实。由于CEF的限制,如果我使用CEF的包装器,项目会变得更混乱,所以我宁愿让v8工作。以下是我实现的CEF的OnContextCreated回调的精简版本:

void ContextHandler::OnContextCreated(
  CefRefPtr<CefBrowser> browser,
  CefRefPtr<CefFrame> frame,
  CefRefPtr<CefV8Context> context)
{
  context->Enter();
  v8::HandleScope scope;
  v8::Handle<v8::Context> v8context = v8::Context::GetCurrent();
  v8::Handle<v8::Object> window = v8context->Global();
  // _appObj is a v8::Handle<v8::ObjectTemplate> member of ContextHandler
  window->Set(v8::String::New("app"), _appObj->NewInstance());
  context->Exit();
}

现在,请注意,虽然CEF在封面下使用v8,但它并没有通过其API公开它。因此,检索v8版本上下文的唯一方法是使用v8::Context::GetCurrent(),理论上它应该返回由CefV8Context包装的v8::Context

还要注意的是,为了进行编译,我需要编译并链接一个单独的v8(静态)库,因为CEF不会通过其(动态)库公开v8。

所以问题来了

在运行项目并调用v8::Context::GetCurrent()时,它在v8库中的某个位置崩溃,并出现EXC_BAD_ACCESS错误。经过进一步的研究,我已经确认,根据CEF的API,我们在调用context->Enter()之后的上下文中是,但根据v8的API,我们不在上下文中,这解释了错误。

从我使用C/C++库的极其有限的经验来看,这似乎意味着我的CEF v8代码和我的v8代码在不同的内存空间中运行。v8是一个静态库,而CEF是一个动态库,所以这会对它产生任何影响吗?

我想知道的是为什么会发生这种情况,我能做些什么来解决这个问题或解决这个问题?

附言:我正在使用C++11和clang通过XCode在Mac OS X上构建这个,但这个问题也困扰着Windows上的VS2012。

要访问CEF使用的V8虚拟机,您必须自己构建CEF。libcef.dll只是"真实"libcef的C++到C++代理,它是一个静态库。当您自己编译CEF时,您可以更改程序以链接到该静态库,而不是DLL的导入库。

通过这样做,您现在需要链接到DLL必须链接到的所有相同的静态库。这包括V8。这将允许直接访问CEF正在使用的同一V8。它还删除了CEF DLL用于与实际CEF代码接口的C++到C++的转换代码。这还将使您可以在需要时直接访问WebCore/WebKit、Chromium、V8以及这些库使用的任何其他库。

请参阅CEF的构建说明:https://code.google.com/p/chromiumembedded/wiki/BranchesAndBuilding

构建完成后,您要为CEF链接到的库是libcef_static.lib.