我的目标是建立一个Game Boy模拟器.为此,我想将SDL2表面嵌入到wxWidgets窗口中.
我找到了这个教程:http://code.technoplaza.net/wx-sdl/part1/,但是我的程序一运行就崩溃了.但我怀疑这是针对SDL1.2的.该计划的一部分如下所示.
看来如果我调用SDL_Init()并尝试显示一个wxFrame(在本例中是MainWindow),它会显示一秒钟的窗口然后程序崩溃.到目前为止,我在程序中评论了对SDL的所有其他调用,所以看起来问题在于在wxFrame上调用Show()并在同一程序中启动SDL2.
所以问题是:SDL2和wxWidgets 3可以一起工作吗?如果没有,你们可以向我推荐一个Game Boy模拟器的GUI吗?wxWidgets是否有像Qt一样的自己的图形框架(我宁愿避免使用Qt)?
非常感谢!
#include "MainApp.h" #include "MainWindow.h" #includenamespace GBEmu { static void initSDL() { //This and SDL_Quit() are the only calls to the SDL library in my code if (SDL_Init(SDL_INIT_EVERYTHING) < 0) { throw std::runtime_error("Fatal Error: Could not init SDL"); } } bool MainApp::OnInit() { try { //If I comment out this line, the MainWindow wxFrame shows up fine. //If I leave both uncommented, the window shows up quickly and then //crashes. initSDL(); //If I comment out this line and leave initSDL() uncommented, //the program will not crash, but just run forever. (new MainWindow("GBEmu", {50,50}, {640,480}))->Show(); } catch(std::exception &e) { wxLogMessage(_("Fatal Error: " + std::string(e.what()))); } return true; } int MainApp::OnExit() { SDL_Quit(); return wxApp::OnExit(); } } wxIMPLEMENT_APP(GBEmu::MainApp);
编辑:这里有关于它如何崩溃的更多信息:它在一个似乎是pthread_mutex_lock反汇编文件的Segfault崩溃.这是控制台中带有堆栈跟踪的输出:
Starting /home/dan/Documents/devStuff/GBEmuWx-build/GBEmuWx... The program has unexpectedly finished. /home/dan/Documents/devStuff/GBEmuWx-build/GBEmuWx crashed Stack trace: Error: signal 11: /home/dan/Documents/devStuff/GBEmuWx-build/GBEmuWx(_ZN5GBEmu7handlerEi+0x1c)[0x414805] /lib/x86_64-linux-gnu/libc.so.6(+0x36ff0)[0x7fb88e136ff0] /lib/x86_64-linux-gnu/libpthread.so.0(pthread_mutex_lock+0x30)[0x7fb88c12ffa0] /usr/lib/x86_64-linux-gnu/libX11.so.6(XrmQGetResource+0x3c)[0x7fb88d1ca15c] /usr/lib/x86_64-linux-gnu/libX11.so.6(XGetDefault+0xc2)[0x7fb88d1a7a92] /usr/lib/x86_64-linux-gnu/libcairo.so.2(+0x94dcf)[0x7fb88af8edcf] /usr/lib/x86_64-linux-gnu/libcairo.so.2(+0x97110)[0x7fb88af91110] /usr/lib/x86_64-linux-gnu/libcairo.so.2(cairo_surface_get_font_options+0x87)[0x7fb88af63e07] /usr/lib/x86_64-linux-gnu/libcairo.so.2(+0x2b61f)[0x7fb88af2561f] /usr/lib/x86_64-linux-gnu/libcairo.so.2(+0x2ef95)[0x7fb88af28f95]
这是它似乎失败的屏幕截图(第7行):
更新:在我的MainWindow类中,我将一个菜单栏附加到窗口.但是,当我注释掉菜单栏的设置时,即使启动SDL,窗口也会显示正常.如果我有initSDL()注释但菜单栏的设置没有注释,菜单栏将显示正常.这是我设置菜单栏的地方:
MainWindow::MainWindow(const wxString &title, const wxPoint &pos, const wxSize &size) :wxFrame(nullptr, wxIDs::MainWindow, title, pos, size){ wxMenu *fileMenu = new wxMenu; fileMenu->Append(wxID_EXIT); wxMenuBar *menuBar = new wxMenuBar; menuBar->Append(fileMenu, "&File"); //commenting this line out will allow the window to showup //and not crash the program SetMenuBar(menuBar); }
RudolfW.. 6
您正在遇到一个旧的heisenbug。
解决方法很简单:您必须在wxWidgets之前(基本上在GTK之前)初始化SDL。为此,您必须进行更改
wxIMPLEMENT_APP(GBEmu::MainApp);
至
wxIMPLEMENT_APP_NO_MAIN(GBEmu::MainApp);
这样wxWidgets不会劫持您的main()。
然后,您必须手动创建main()。在其中,初始化SDL,然后调用wxEntry():
int main(int argc, char** argv) { if (SDL_Init(SDL_INIT_EVERYTHING) < 0) { std::cerr << "Could not initialize SDL.\n"; return 1; } return wxEntry(argc, argv); }
有关该错误的更多信息:
我在Google上搜索了一下,发现这些错误多年来已经出现在几个地方。许多错误跟踪器中都有打开的报告,这些报告的堆栈跟踪与您在此处获得的堆栈跟踪非常相似(带有调试符号)。
我能找到的最早的报告是cairo bug跟踪程序(https://bugs.freedesktop.org/show_bug.cgi?id=4373)的2005(!! )。
我最好的猜测是该错误的真正隐藏位置是在GTK,cairo或X中。不幸的是,我目前没有时间更深入地研究它。