My goal is to build a Game Boy emulator. In order to do this, I would like to embed an SDL2 surface into a wxWidgets window.
I found this tutorial: http://code.technoplaza.net/wx-sdl/part1/, but my program crashes as soon as I run it. However I suspect this was intended for SDL1.2. Part of the program is shown below.
It seems that if I call SDL_Init() and also attempt to show a wxFrame (which, in this case, is MainWindow), it shows the window for a second and then the program crashes. I commented all other calls to SDL in my program so far, so it seems the problem lies with calling Show() on a wxFrame and initing SDL2 in the same program.
So the question is: can SDL2 and wxWidgets 3 work together? If not, could you guys suggest to me good alternatives a GUI of a Game Boy emulator? Does wxWidgets have its own graphics frame like Qt does (I'd rather avoid Qt)?
Thanks very much!
#include "MainApp.h"
#include "MainWindow.h"
#include <stdexcept>
namespace 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);
EDIT: Here is more information on how it crashes: It crashes with a Segfault in what seems to be the pthread_mutex_lock disassembly file. This is the output in the console with stack trace:
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]
This is a screenshot of where it seems to fail (line 7):
Update: In my MainWindow class, I attach a menu bar to the window. However, it seems when I comment out the setting of the menu bar, the window will show up fine even with initing of SDL. The menu bar will show up fine if I have initSDL() commented out but not the setting of the menu bar. Here is where I set the menu bar:
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);
}
You are experiencing an old heisenbug.
The workaround is simple: you have to initialize SDL before wxWidgets (basically, before GTK). To achieve this, you have to change
wxIMPLEMENT_APP(GBEmu::MainApp);
to
wxIMPLEMENT_APP_NO_MAIN(GBEmu::MainApp);
so that wxWidgets doesn't hijack your main().
Then you have to create main() manually. In it, initialize SDL, then call 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);
}
More about the bug:
I have googled around a bit and found that this bug has come up in a few places over the years. There are open reports in many bug trackers that have stack traces very similar to the one you get here (with debug symbols).
The oldest report I could find is from 2005 (!!) from the cairo bug tracker (https://bugs.freedesktop.org/show_bug.cgi?id=4373).
My best guess is that the real hiding place of this bug in either in GTK, cairo, or X. Unfortunately I do not currently have the time to look into it more in depth.
Related
-I am new to C++ and SFML and want to import a png file.
-It worked a view times, but afterwards I got the
message "Build failed, run last success?" most of the time. Sometimes its still working.
-there is no "real" error, so its hard to figure out, what the problem is
-I read earlier, that switching from Debug to Release-Mode could be a reason, but it didnt helped
its working when I dont use:
if (!texture.loadFromFile("assets/player.png"))
{
std::cout << "Could not load png \n";
return 0;
}
-> but, ofcourse, the sprite is missing then.
I would be happy to have a solution/reason for this or a topic I missed so far to read/ learn about.
Im happy about advices.
Thanks so far.
Alex
VISUAL STUDIO 2019
x64
SFML-2.5.1
WHOLE CODE:
#include"SFML/Graphics.hpp"
#include<iostream>
#include"main.h"
int main(int argc, char** argv[])
{
sf::RenderWindow window(sf::VideoMode(1200,800), "bimWindow");
sf::RectangleShape rs(sf::Vector2f(1000, 700));
rs.setFillColor(sf::Color::Green);
sf::Event event;
sf::Texture texture;
if (!texture.loadFromFile("assets/player.png"))
{
std::cout << "Could not load png \n";
return 0;
}
sf::Sprite sprite;
sprite.setTexture(texture);
sprite.setPosition(100,100);
//sprite.scale(sf::Vector2f(3, 3));
rs.setPosition(80, 80);
// run the program as long as the window is open:
while (window.isOpen())
{
//let window open i guess.
while (window.pollEvent(event)); //stay true as long aas it didnt happen or so
{
// "close requested" event:close the window
if(event.type == sf::Event::Closed)
window.close();
}
//RENDER:
window.clear();
window.draw(rs);
window.draw(sprite);
window.display();
}
return 0;
}
Try making sure that the "assets/player.png" file is inside your solution directory (the folder with the .sln file.) Your code seems to run fine on my end, and that is the only error I can think of. If you can, it would help to have the error message(s) that you are receiving. If the png file is in the right place and you still get errors, I would recommend reinstalling SFML and following a tutorial online to ensure that you get everything set up properly.
Im trying to use the inter-widget drag-and-drop functionalities in GTK3 with gtkmm. Im using Windows 7 x64 (msys2) and gcc 5.3.0.
When i start dragging, the mouse cursor vanishes and the DnD icon is shown at the upper left corner of the screen. Is this a bug or is there something wrong in my code?
Here you can see a very small test application with Gtk::CheckButton as drag source and drag destination.
#include <iostream>
#include <gtkmm-3.0/gtkmm.h>
struct DragButton : Gtk::CheckButton{
DragButton(){
this->signal_drag_begin().connect([](const Glib::RefPtr<Gdk::DragContext>& ctx){
ctx->set_icon();
});
this->drag_source_set({Gtk::TargetEntry("testdata")});
this->drag_dest_set({Gtk::TargetEntry("testdata")});
this->signal_drag_data_get().connect(
[this](const Glib::RefPtr<Gdk::DragContext>&,Gtk::SelectionData& s,guint,guint ){
std::cout << "sending data." << std::endl;
}
);
this->signal_drag_data_received().connect(
[](const Glib::RefPtr<Gdk::DragContext>& c,int,int,const Gtk::SelectionData&,guint,guint time){
std::cout << "receiving data" << std::endl;
c->drop_finish(true,time);
}
);
}
};
int main(){
auto app = Gtk::Application::create("test");
auto settings = Gtk::Settings::get_default();
settings->set_property<Glib::ustring>("gtk-font-name","Sans 10");
Gtk::Window window;
window.set_default_size(100,50);
Gtk::Box box;
for(int i = 0; i < 3; i++){
box.pack_end(*Gtk::manage(new DragButton));
}
window.add(box);
window.show_all();
app->run(window);
}
This screenshot shows the output:
I noticed the same behaviour here. Even with "official" gnome/gtk applications. For example, let's try to drag&drop widgets in Glade: you will have the same "strange" effect.
I think it's a bug of gtk libraries in Windows, but I can't imagine why this isn't solved yet, considering drag&drop is a very useful and used operation.
I found the problem. I found out here that the adwait-icon-theme that is used as a default was not fully windows-compatible. The cursors .cur format were missing. This commit fixed the problem, I had to install the new version of the theme.
So, I'm making a game using SFML in C++, but when I tried adding a image a really weird OpenGL(i think) error popped up. Doesn't make any sense at all.
First my console was spammed with random text and symbols, then the application crashed and visual studio told me this :
Exception thrown at 0x618EDBF4 (vcruntime140.dll) in SFML_Game.exe: 0xC0000005: Access violation reading location 0x00C54000.
It sounds like it has something to do with not being able to read my picture file I added, though i don't know whats wring with it.
The location of the image is in the same folder my "SFML_Game.vcxproj" is.
I also have no chance of seeing if "Could not load player image" was printed in console since the spam is too quick.
Edit I can see that the picture failed to load now, here's a picture... :
Console Picture
Here's my current code :
#include<iostream>
#include<SFML/Graphics.hpp>
#include <string>
int main(int argc, char* argv[])
{
// Creates a window
sf::RenderWindow Window(sf::VideoMode(800, 600), "SFML Game Engine");
sf::Texture pTexture;
sf::Sprite playerImage;
if (!pTexture.loadFromFile("Player.png"))
{
std::cout << "Could not load player image" << std::endl;
}
playerImage.setTexture(pTexture);
while (Window.isOpen())
{
sf::Event Event;
while (Window.pollEvent(Event) && Window.hasFocus())
{
switch (Event.type)
{
case sf::Event::Closed:
Window.close();
break;
}
}
Window.draw(playerImage);
Window.display();
}
}
So, it seems that my code was fine and it was a linker error.
I didn't know the difference between static-dynamic, static and dynamic libraries, so I just put them all in there, after removing some of them it started working.
At least in debugging mode.
Pretty much, if someone else has this problem, look up how to set SFML up on their website instead of a video tutorial. ^^
In my company, we are developing with Embarcadero-C++-IDE (which is very uncomfortable). To start moving away, we port individual dialogs in a dll to Qt. My qt-dll-code Looks like this for example
extern "C" ROBOTECHPOLYLINEDIALOGSHARED_EXPORT void popupRoboTechDialog()
{
if( ! QApplication::instance() )
{
int argc = 1;
char *argv[] = {"Design polyline"};
QApplication app(argc, argv);
RoboTechPolyline dialog;
dialog.show();
app.exec();
}
else
{
RoboTechPolyline Dialog;
Dialog.exec();
}
}
Trying to start the Dialog from another thread like here Starting Qt GUI from dll (in DLLStart function) did make my Dialog unresponsive, but I don't think the question and mine relate too much.
I'm loading this Dll dynamically from the main-application and it works fine. However, when I make the Dialog Pop up a second time I get an "Access Violation at address .. in module MSVCR110D.dll" and on the third time, I get "ASSERT failure in QCoreApplication , there should be only one application object". So I always Need to Close the whole application in order to make the Dialog appear a second time, which greaty slows down work.
If I add at the bottom the line
QApplication::quit()
the Dialog appears a second time, but the Programm crashes on closing this second Dialog.
The code to load the dll is as follows
HINSTANCE lib = ::LoadLibrary(L"RoboTechPolylineDialog.dll");
if(!lib)
{
ShowMessage("Unable to load RoboTechPolylineDialog.dll");
return;
}
typedef void ( *POPUP_ROBO_TECH_DIALOG )();
POPUP_ROBO_TECH_DIALOG fp = (POPUP_ROBO_TECH_DIALOG) ::GetProcAddress(lib, "popupRoboTechDialog");
if(!fp)
{
ShowMessage("Unable to load function popupRoboTechDialog from RoboTechPolylineDialog.dll");
::FreeLibrary(lib);
return;
}
(*fp)( );
FreeLibrary(lib);
So why am I constructing more than one QApplication at a time? I can in above code replace the line
(*fp)();
with
(*fp)();
(*fp)();
and the Dialog appears twice and everything works greatly. But how can the call to ::FreeLibrary(lib) make things fail.
Can anyone help me? Any help, Workarounds, etc.. is appreciated.
This should work:
#include <QApplication>
#include <QString>
#include <QDialog>
class App {
QApplication *_app;
public:
App(int argc = 0, char** argv = NULL)
: _app(new QApplication(argc, argv))
{
}
~App() {
delete _app;
}
};
void dialog()
{
static int argc = 1;
static char *argv[] = {"Design polyline"};
static App(argc, argv);
QDialog dlg;
dlg.exec();
}
void main()
{
dialog();
dialog();
dialog();
}
Another advice: load Qt libs from as subpath since you could find dll conflict with other apps using it on the same folder (personal experience)
C++ fltk: I have a window with an in_box and an out_box, how do I make it so that the user can type into the in_box hit enter, then proceed with the rest of the event. Right now the window just shows up and goes away.
Window w(Point(100,100),200,200, "Category Sales");
In_box cat_in(Point(75,75),100,20,"Category:");
Out_box cat_out(Point(75,115),100,20,"Sales:");
w.attach(cat_in);
w.attach(enter);
category = cat_in.get_string();
I'm not sure exactly if this will fix your problem, but to keep the window open, return Fl::run().
I have never seen In_box and Out_box before, so I will assume those are your own classes or structures...
As pointed before - the easiest way to start the FLTK event loop is to use Fl::run() or (FLTK2) fltk::run().
So, here your code should look something like (FLTK2):
#include <fltk/Window.h>
#include <fltk/Widget.h>
#include <fltk/run.h>
using namespace fltk;
int main(int argc, char **argv) {
// your code begins
Window w(Point(100,100),200,200, "Category Sales");
In_box cat_in(Point(75,75),100,20,"Category:");
Out_box cat_out(Point(75,115),100,20,"Sales:");
w.attach(cat_in);
w.attach(enter);
category = cat_in.get_string();
// your code ends
w->end();
w->show(argc, argv);
return run(); // this line is the most important, here we start the FLTK event-loop
}