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

C++ 使用v8的共享库与静态链接的v8不兼容?,c++,shared-libraries,v8,static-linking,chromium-embedded,C++,Shared Libraries,V8,Static Linking,Chromium Embedded,下面是一些真实问题的背景: 我正在使用一个项目(CEF),并为在嵌入式浏览器中运行的JavaScript提供本地C++函数绑定。 具体来说,我要做的是在加载任何页面或上下文之前构造一个v8::ObjectTemplate,然后在CEF的OnContextCreated回调中,创建该模板的新实例,并将其作为属性添加到全局窗口对象中 问题在于,CEF的API包装了v8上下文和值,为您提供了一个指向接口的(智能)指针,完全隐藏了它在幕后使用v8的事实。由于CEF的限制,如果我使用CEF的包装器,项目会

下面是一些真实问题的背景:

我正在使用一个项目(CEF),并为在嵌入式浏览器中运行的JavaScript提供本地C++函数绑定。 具体来说,我要做的是在加载任何页面或上下文之前构造一个

v8::ObjectTemplate
,然后在CEF的
OnContextCreated
回调中,创建该模板的新实例,并将其作为属性添加到全局
窗口
对象中

问题在于,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();
}
void ContextHandler::OnContextCreated(
CefRefPtr浏览器,
CefRefPtr框架,
CefRefPtr(上下文)
{
上下文->输入();
v8:手镜范围;
v8::Handle v8context=v8::Context::GetCurrent();
v8::Handle window=v8context->Global();
//_appObj是ContextHandler的v8::Handle成员
窗口->设置(v8::字符串::新建(“应用程序”),\u appObj->NewInstance();
上下文->退出();
}
现在,请注意,虽然CEF在幕后使用v8,但它并没有通过其API公开它。因此,检索v8版本的上下文的唯一方法是使用
v8::context::GetCurrent()
,从理论上讲,它应该返回由
CefV8Context
包装的
v8::context

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

所以问题出在这里

在运行项目并调用
v8::Context::GetCurrent()
时,它会在v8库中的某个地方发生
EXC\u BAD\u ACCESS
错误而崩溃。经过进一步研究,我已经确认,根据CEF的API,我们在调用
context->Enter()
后处于上下文中,但根据v8的API,我们不在上下文中,这解释了错误

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

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


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

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

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

请参阅CEF的构建说明:


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

静态链接的v8与CEF使用的v8没有关系。这不是一个不同的地址空间,但是库的两个实例(在CEF中使用的一个和静态链接的一个)彼此不了解。幸运的是,CEF是开源的,所以您可以检查CEF的v8库在哪里(以及它是如何加载的),如果需要,甚至可以添加“后门”。但是,看一下'CefV8Context
,我发现它有一个
GetGlobal()`方法,它有一个采用键/值对的
SetValue()
方法重写。也就是说,我看到了您在CEF?@Yakk中似乎需要的接口,
GetGlobal()->SetValue()
只接受
CefV8Value
s(CEF对
v8::Value
的包装实现),而CEF对您可以使用它们施加了限制,因此直接使用v8。至于后门,CEF在编译时做了很多疯狂的事情,因此,CEF方法只能返回原语、指针和其他CEF类。最后一点:您建议我如何使用与CEF“相同”的v8?我要么想知道如何使用
CefV8Value
做我想做的事情,要么扩展
CefV8Value
做我想做的事情,要么想知道如何从CEF生成一个进入
v8
的后门,大致顺序是越来越绝望,越来越有可能在今后的道路上引发问题。@AustinHyde:你解决了这个问题吗?我现在也有同样的问题。你能把解决方案贴出来吗?谢谢@用户3不,从来没想过。我相信我只是接受了它,并与CEF合作。以下是该项目的代码(如果有帮助的话):