Вот некоторая предыстория реальной проблемы:
Я работаю над проектом, используя Chromium Embedded Framework (CEF) и v8 обеспечить привязку нативных функций C ++ к JavaScript, работающему во встроенном браузере.
В частности, я пытаюсь создать 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()
который в теории должен вернуть v8::Context
будучи обернутым CefV8Context
,
Также обратите внимание, что для того, чтобы это скомпилировать, мне нужно скомпилировать и связать отдельный v8 (статическая) библиотека, еще раз, потому что CEF не предоставляет v8 через свою (динамическую) библиотеку.
Так вот в чем проблема:
После запуска проекта и вызова v8::Context::GetCurrent()
сбой с EXC_BAD_ACCESS
ошибка где-то в библиотеке v8. После дальнейших исследований я подтвердил, что в соответствии с API CEF мы являются в контексте после вызова context->Enter()
, но в соответствии с API v8, мы не в контексте, который объясняет ошибку.
Из моего крайне ограниченного опыта работы с библиотеками C / C ++, мне кажется, что это означает, что код CEF v8 и мой код v8 выполняются в разных пространствах памяти. v8 — это статическая библиотека, а CEF — динамическая библиотека, так как это повлияет на нее?
Я хотел бы знать, почему это происходит, и что я могу сделать, чтобы это исправить или обойти это?
PS: я создаю это с использованием C ++ 11 и clang на Mac OS X через XCode, но эта проблема также мешает VS2012 на Windows.
Чтобы получить доступ к виртуальной машине V8, используемой CEF, вам придется создать CEF самостоятельно. Libcef.dll — это просто прокси C ++ to C ++ для «настоящего» libcef, который является статической библиотекой. Когда вы сами компилируете CEF, вы можете изменить свои программы так, чтобы они ссылались на эту статическую библиотеку, а не на библиотеку импорта для DLL.
Сделав это, вы теперь обязаны ссылаться на все те же статические библиотеки, на которые должна была ссылаться DLL. Это включает в себя V8. Теперь это позволит прямой доступ к тому же V8, который использует CEF. Он также удаляет код перевода C ++ в C ++, который CEF DLL использовал для взаимодействия с реальным кодом CEF. Это также даст вам прямой доступ к WebCore / WebKit, Chromium, V8 и любым другим библиотекам, которые используются теми, когда вы этого хотите или нуждаетесь.
Обратитесь к инструкции по сборке CEF: https://code.google.com/p/chromiumembedded/wiki/BranchesAndBuilding
После сборки библиотека, на которую вы хотите сослаться для CEF, — это libcef_static.lib.
Других решений пока нет …