That’s pretty cool!
By the way, the reason CEF is crashing on you on exit may be because you’re not initializing it correctly. I quickly tested out your code on Linux (which didn’t work out of the box), and realised that you need to setup your main function differently. CEF spawns multiple processes since it does JS + rendering in a separate process, so it invokes the “parent” process multiple times. You need to take this into account, or define a separate subprocess for CEF to spawn (CefSettings.browser_subprocess_path).
I have not tested this on Windows, but I did my best to “blind code” to make this work. Have a go and see how it works for you.
First, remove everything CEF related from the MyApp constructor (MyApp.cpp):
//
// Constructor
//
MyApp::MyApp(Context* context) :
Application(context)
{
}
You need more control over the main function when dealing with CEF3 (unless you define a separate subprocess), so skip the Urho3D DEFINE_APPLICATION_MAIN() macro for now (main.cpp):
#include "MyApp.hpp"
#include "include/cef_app.h"
#include <iostream>
#if !defined(WIN32)
#include <unistd.h>
#endif
using std::cout;
using std::endl;
//DEFINE_APPLICATION_MAIN(MyApp)
int RunApplication()
{
Urho3D::Context* context = new Urho3D::Context();
MyApp* application = new MyApp(context);
return application->Run();
}
#if defined(WIN32)
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd)
#else
int main(int argc, char** argv)
#endif
{
#if !defined(WIN32)
pid_t t_pidid = getpid();
cout << "Spawning process [" << t_pidid << "] int main(argc, argv);" << endl;
#endif
#if defined(WIN32)
CefMainArgs args(hInstance);
#else
CefMainArgs args(argc, argv);
#endif
{
// https://bitbucket.org/chromiumembedded/cef/wiki/GeneralUsage
// By default the main application executable will be spawned multiple times to represent separate processes.
// This is handled via command-line flags that are passed into the CefExecuteProcess function.
// If the main application executable is large, takes a long time to load, or is otherwise unsuitable for non-browser processes the host can use a
// separate executable for those other processes. This can be configured via the CefSettings.browser_subprocess_path variable.
// See the ?Application Structure? section for more information.
int result = CefExecuteProcess(args, nullptr, nullptr);
// checkout CefApp, derive it and set it as second parameter, for more control on
// command args and resources.
if (result >= 0) // child proccess has endend, so exit.
{
return result;
}
if (result == -1)
{
// we are here in the father proccess.
}
}
CefSettings settings;
// checkout detailed settings options http://magpcss.org/ceforum/apidocs/projects/%28default%29/_cef_settings_t.html
settings.windowless_rendering_enabled = true;
//settings.no_sandbox = 1; // Use this to run without sandbox
//settings.single_process = true;
//settings.multi_threaded_message_loop = true;
bool result = CefInitialize(args, settings, nullptr, nullptr);
// CefInitialize creates a sub-proccess and executes the same executeable, as calling CefInitialize, if not set different in settings.browser_subprocess_path
// if you create an extra program just for the childproccess you only have to call CefExecuteProcess(...) in it.
if (!result)
{
// handle error
return 0;
}
Urho3D::ParseArguments(argc, argv);
return RunApplication();
}
Added some Linux specific process debug output here, so don’t worry about that, just wanted to demonstrate what is going on. Output of process:
[gunnar@G750JX Bin_Release]$ ./cef3_test -x 1280 -y 800
Spawning process [6477] int main(argc, argv);
Spawning process [1] int main(argc, argv);
[Wed Apr 15 22:04:27 2015] INFO: Opened log file Urho3D.log
[Wed Apr 15 22:04:27 2015] INFO: Created 3 worker threads
[Wed Apr 15 22:04:27 2015] INFO: Added resource path /home/gunnar/code/Urho3D-CEF3/Bin_Release/Data/
[Wed Apr 15 22:04:27 2015] INFO: Added resource path /home/gunnar/code/Urho3D-CEF3/Bin_Release/CoreData/
Spawning process [6497] int main(argc, argv);
[0415/220427:FATAL:scoped_file.cc(29)] Check failed: 0 == IGNORE_EINTR(close(fd)). : Bad file descriptor
[Wed Apr 15 22:04:27 2015] INFO: Set screen mode 1920x1080 fullscreen
[Wed Apr 15 22:04:27 2015] INFO: Initialized input
[Wed Apr 15 22:04:27 2015] INFO: Initialized user interface
[Wed Apr 15 22:04:27 2015] INFO: Initialized renderer
[Wed Apr 15 22:04:27 2015] INFO: Set audio mode 44100 Hz stereo interpolated
[Wed Apr 15 22:04:27 2015] INFO: Initialized engine
[0415/220429:WARNING:channel.cc(547)] Failed to send message to ack remove remote endpoint (local ID 1, remote ID 1)
[0415/220429:WARNING:channel.cc(547)] Failed to send message to ack remove remote endpoint (local ID 2147483648, remote ID 2)
As you can see, the process is invoked three times (not sure about what the process with ID=1 is), but what you get is the “main” process that contains your application logic (Urho3D in this case), and a separate process that does the V8 JS processing and Blink rendering.
Spawning process [6477] int main(argc, argv);
Spawning process [1] int main(argc, argv);
Spawning process [6497] int main(argc, argv);
I’m actually surprised it worked on Windows at all…