I'm trying to write a C++ wrapper class around some SDL2 classes.
Now I have this working code, which displays a red screen for 5 seconds (as you can see, my wrapper classes are in namespace sdl2cc):
int main(void)
{
if (SDL_Init(SDL_INIT_VIDEO) < 0) return 1;
sdl2cc::Window window{"SDL_RenderClear"s, sdl2cc::Rect{sdl2cc::Point{SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED}, sdl2cc::Dimension{512, 512}}, {}};
sdl2cc::Renderer renderer{window, {}};
renderer.draw_color(sdl2cc::Color{sdl2cc::RGB{255,0,0}, sdl2cc::Alpha{255}});
SDL_RenderClear(renderer.data());
// renderer.clear();
SDL_RenderPresent(renderer.data());
// renderer.present();
SDL_Delay(5000);
SDL_Quit();
}
In the wrapper class of SDL2's SDL_Renderer I have a std::unique_ptr data member renderer_ pointing to an actual SDL_Renderer.
renderer.data() exposes this pointer (return this->renderer_.get();).
I want to get the member functions renderer.clear() and renderer.present() to work. Sadly neither do. This is how they look:
void sdl2cc::Renderer::clear(void)
{
if (SDL_RenderClear(this->data()) < 0)
{
std::cerr << "Couldn't clear rendering target with drawing color:" << ' ' << SDL_GetError() << '\n';
}
}
void sdl2cc::Renderer::present(void)
{
SDL_RenderPresent(this->data());
}
If I just use renderer.clear(), it will print my error message + Invalid renderer.
If I just use renderer.present(), it will show a black screen.
What is wrong?
Why are my own functions and the SDL functions not equivalent?
The problem seems to lie in the function call:
SDL_RenderClear(renderer.data()); // works
// somewhere else:
void sdl2cc::Renderer::clear(SDL_Renderer* r)
{
if (SDL_RenderClear(r) < 0)
{
std::cerr << "Couldn't clear rendering target with drawing color:" << ' ' << SDL_GetError() << '\n';
}
}
renderer.clear(renderer.data()); // doesn't work: Invalid Renderer
But I still don't understand where the problem lies. To me it seems to accomplish the same thing, but somehow one throws an error, the other doesn't.
EDIT:
Another interesting thing, trying to step in at renderer.clear() with lldb goes directly to the next line, without actually stepping in... I don't even.
The problem had to do with multiply linked libraries.
I compiled my own library with the SDL2 libraries and then compiled my executable with my library and the SDL2 libraries.
Related
After realizing it is nearly impossible to find help on getting keybindings to work with the C plugin in MPV (Possible to allow key bindings with MPV C API when no video (GUI) is being shown?), I decided to learn some Lua to help with the cause. Problem is, the docs aren't very clear on how to add Lua scripts with the C plugin, what I could find out was that check_error(mpv_set_option_string(ctx, "load-scripts", "yes")); should be called before initializing mpv in the C plugin, which points out that there should be a way to add scripts... When loading a script in the terminal you can do mpv video.mp4 --scripts="script_name.lua" and that will call the script from inside $HOME/.config/mpv... How do I achieve the calling of Lua scripts in the C plugin for MPV? I tried a few things including check_error(mpv_set_option_string(ctx, "scripts", "test.lua")); and check_error(mpv_set_property_string(ctx, "scripts", "test.lua")); and const char *cmd2[] = {"scripts", "test.lua", NULL}; check_error(mpv_command(ctx, cmd2));, none of which worked...
How do I call a Lua script for MPV from the C Plugin?
Below is the code I'm using to test things out:
// Build with: g++ main.cpp -o output `pkg-config --libs --cflags mpv`
#include <iostream>
#include <mpv/client.h>
static inline void check_error(int status)
{
if (status < 0)
{
std::cout << "mpv API error: " << mpv_error_string(status) << std::endl;
exit(1);
}
}
int main(int argc, char *argv[])
{
if (argc != 2)
{
std::cout << "pass a single media file as argument" << std::endl;
return 1;
}
mpv_handle *ctx = mpv_create();
if (!ctx)
{
std::cout << "failed creating context" << std::endl;
return 1;
}
// Enable default key bindings, so the user can actually interact with
// the player (and e.g. close the window).
check_error(mpv_set_option_string(ctx, "input-default-bindings", "yes"));
mpv_set_option_string(ctx, "input-vo-keyboard", "yes");
check_error(mpv_set_option_string(ctx, "load-scripts", "yes"));
check_error(mpv_set_option_string(ctx, "scripts", "test.lua")); // DOES NOT WORK :(
int val = 1;
check_error(mpv_set_option(ctx, "osc", MPV_FORMAT_FLAG, &val));
// Done setting up options.
check_error(mpv_initialize(ctx));
// Play the file passed in as a parameter when executing program.
const char *cmd[] = {"loadfile", argv[1], NULL};
check_error(mpv_command(ctx, cmd));
// check_error(mpv_set_option_string(ctx, "scripts", "test.lua"));
check_error(mpv_set_option_string(ctx, "shuffle", "yes")); // shuffle videos
check_error(mpv_set_option_string(ctx, "loop-playlist", "yes")); // loop playlists
// check_error(mpv_set_option_string(ctx, "aspect", "0:0")); // set aspect
// Let it play, and wait until the user quits.
while (1)
{
mpv_event *event = mpv_wait_event(ctx, 10000);
std::cout << "event: " << mpv_event_name(event->event_id) << std::endl;
if (event->event_id == MPV_EVENT_SHUTDOWN)
break;
}
mpv_terminate_destroy(ctx);
return 0;
}
After playing around more with the mpv_set_property_string command, I discovered that you have to specify the FULL path to the Lua file, it by defaults searches for the file in the directory it is being played in, so if I tried to play it in /home/ it will search for /home/test.lua, so to get it to work I had to do check_error(mpv_set_property_string(ctx, "scripts", "/home/netsu/.config/mpv/test.lua")); (give the absolute path)
I am just starting with OGDF and try to get a hang of it by running some of the examples that are on the OGDF webpage under How-Tos.
My Code compiles, but it segfaults when I try to call a GraphAttributes function on a node.
Here my Code:
ogdf::Graph G;
ogdf::GraphAttributes GA(G);
if (!ogdf::GraphIO::readGML(G, "sierpinski_04.gml") ) {
std::cerr << "Could not load sierpinski_04.gml" << std::endl;
return 1;
}
ogdf::node v;
GA.setAllHeight(10.0);
GA.setAllWidth(10.0);
ogdf::FMMMLayout fmmm;
fmmm.useHighLevelOptions(true);
fmmm.unitEdgeLength(15.0);
fmmm.newInitialPlacement(true);
//fmmm.qualityVersusSpeed(ogdf::FMMMLayout::qvsGorgeousAndEfficient);
fmmm.call(GA);
ogdf::GraphIO::writeGML(GA, "sierpinski_04-layout.gml");
for(v=G.firstNode(); v; v=v->succ()) {
std::cout << v << std::endl;
//the following line causes the segfault
double xCoord = GA.x(v);
}
If I comment out the line that I mention in the comment is causing the segfault the program runs fine without a segfault.
If I then look into the written out .gml file the nodes have x- and y- Coordinates.
I am getting the following message:
MT: /home/work/lib/OGDF-snapshot/include/ogdf/basic/NodeArray.h:174: T& ogdf::NodeArray<T>::operator[](ogdf::node) [with T = double; ogdf::node = ogdf::NodeElement*]: Assertion `v->graphOf() == m_pGraph' failed.
It also happens when I call a different function on GraphAttributes, as for example .idNode(v).
Can someone point me in the right direction why this is happening? I do absolutly not understand where this is coming from by now, and OGDF is to big to just walk through the code and understand it. (At least for me)
Thank you very much in advance!
Unfortunatelly, your problem is not easy to reproduce.
My intuition would be to initialize the GraphAttributes after loading the Graph from the file.
ogdf::Graph G;
if (!ogdf::GraphIO::readGML(G, "sierpinski_04.gml") ) {
std::cerr << "Could not load sierpinski_04.gml" << std::endl;
return 1;
}
ogdf::GraphAttributes GA(G, ogdf::GraphAttributes::nodeGraphics |
ogdf::GraphAttributes::nodeStyle |
ogdf::GraphAttributes::edgeGraphics );
Or to call the initAttributes after loading the graph.
ogdf::Graph G;
ogdf::GraphAttributes GA(G);
if (!ogdf::GraphIO::readGML(G, "sierpinski_04.gml") ) {
std::cerr << "Could not load sierpinski_04.gml" << std::endl;
return 1;
}
GA.initAttributes(ogdf::GraphAttributes::nodeGraphics |
ogdf::GraphAttributes::nodeStyle |
ogdf::GraphAttributes::edgeGraphics);
Hopefully, that's helping.
For me, building without -DOGDF_DEBUG worked.
The assertion (which accidentally fails) is only checked in debug mode.
In Graph_d.h:168:
#ifdef OGDF_DEBUG
// we store the graph containing this node for debugging purposes
const Graph *m_pGraph; //!< The graph containg this node (**debug only**).
#endif
I'm following this tutorial in the official PCL documentation for the class PCLVisualizer:
http://pointclouds.org/documentation/tutorials/pcl_visualizer.php
and I'm having troubles with the keyboard acquisition: when I select the render window, where the pointcloud is displayed, and try to press "r" or "q", nothing happens and when I try to press the mouse left button, the following text is displayed:
Left mouse button released at position (413, 475)
and the following error is raised (at runtime):
Assertion failed: (px != 0), function operator->, file /usr/local/include/boost/smart_ptr/shared_ptr.hpp, line 687.
Abort trap: 6
I saw that this kind of error happens when you don't initialize the boost::shared_ptr in the declaration of the variable. But in the code listed in the documentation the variable is well defined, so I suppose that the problem concerns the shared_ptr.hpp library, or it isn't?
I've searched over the Internet for a solution, but I haven't found nothing that could solve the issue.
Is there someone that is capable of acquiring keystrokes in the pointcloud's render window by running it on OS X?
If the question is not clear, please let me know.
Thanks a lot for any help or information!
You do not show any code so it's hard to tell what's wrong in your program.
Here is a working example, tested on Ubuntu 14.04 with PCL latest trunk (VTK trunk):
#include <iostream>
#include <pcl/visualization/pcl_visualizer.h>
void keyboardEventOccurred(const pcl::visualization::KeyboardEvent &event, void* viewer_void)
{
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer = *static_cast<boost::shared_ptr<pcl::visualization::PCLVisualizer> *>(viewer_void);
if (event.getKeySym() == "r" && event.keyDown())
std::cout << "'r' was pressed" << std::endl;
if (event.getKeySym() == "h" && event.keyDown())
std::cout << "'h' was pressed" << std::endl;
}
void mouseEventOccurred(const pcl::visualization::MouseEvent &event, void* viewer_void)
{
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer = *static_cast<boost::shared_ptr<pcl::visualization::PCLVisualizer> *>(viewer_void);
if (event.getButton() == pcl::visualization::MouseEvent::LeftButton &&
event.getType() == pcl::visualization::MouseEvent::MouseButtonRelease)
std::cout << "Left mouse button released at position (" << event.getX() << ", " << event.getY() << ")" << std::endl;
}
int main()
{
pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer);
viewer->addCoordinateSystem();
viewer->registerKeyboardCallback(keyboardEventOccurred, (void*)&viewer);
viewer->registerMouseCallback(mouseEventOccurred, (void*)&viewer);
viewer->spin();
}
Note that some key-strokes are already used by the PCL visualizer for some actions (press h for more details), but it does not prevent you from using them as well.
My goal is to be able to use a joystick inside of Qt (to add a piloting task to an existing Qt app)
Note : Qt 5.4 // SFML 2.2 (running on CentOS7)
In order to do so, I used the tutorial on the sfml website explaining how to insert an sfml window inside of a Qt widget. That tutorial ( http://www.sfml-dev.org/tutorials/1.6/graphics-qt.php ) being too old, I had to change some things in order to update it for sfml 2.2.
However things do not work as intended and while it does compile, it seems to be unable to create the sfml window from the winid and end up crashing
Here is the part of code corresponding to the window creation :
void QSFMLCanvas::showEvent(QShowEvent*)
{
if (!myInitialized)
{
std::cout << "Bla" << std::endl;
// Under X11, we need to flush the commands sent to the server to ensure that
// SFML will get an updated view of the windows
#ifdef Q_WS_X11
XFlush(QX11Info::display());
#endif
std::cout << "Blabla" << std::endl;
// Create the SFML window with the widget handle
sf::WindowHandle HANDLE;
HANDLE = static_cast<sf::WindowHandle>(winId());
std::cout << HANDLE << std::endl;
std::cout << "Blablabla" << std::endl;
sf::RenderWindow::create(HANDLE);
std::cout << "Blablablabla" << std::endl;
// Let the derived class do its specific stuff
OnInit();
// Setup the timer to trigger a refresh at specified framerate
connect(&myTimer, SIGNAL(timeout()), this, SLOT(repaint()));
myTimer.start();
myInitialized = true;
}
}
And here is the output
Bla
Blabla
35651593
Blablabla
...and crash
As you see it seems to have no trouble obtaining the window handle but can't create the sfml renderwindow from it
Note that there is a static_cast for the handle that isn't there in the tutorial. Different questions suggested putting a reinterpret_cast but then it gives me this error
QSFMLCanvas.cpp: In member function ‘virtual void QSFMLCanvas::showEvent(QShowEvent*)’:
QSFMLCanvas.cpp:48:60: erreur: invalid cast from type ‘WId {aka long long unsigned int}’ to type ‘sf::WindowHandle {aka long unsigned int}’
HANDLE = reinterpret_cast<sf::WindowHandle>(winId());
Is there a way to solve this problem ? Or are just SFML & Qt fated to never work together anymore ?
Thank you for your help
I'm struggling with creating a window with the GLFW 3 function, glfwCreateWindow.
I have set an error callback function, that pretty much just prints out the error number and description, and according to that the GLFW library have not been initialized, even though the glfwInit function just returned success?
Here's an outtake from my code
// Error callback function prints out any errors from GFLW to the console
static void error_callback( int error, const char *description )
{
cout << error << '\t' << description << endl;
}
bool Base::Init()
{
// Set error callback
/*!
* According to the documentation this can be use before glfwInit,
* and removing won't change anything anyway
*/
glfwSetErrorCallback( error_callback );
// Initialize GLFW
/*!
* This return succesfull, but...
*/
if( !glfwInit() )
{
cout << "INITIALIZER: Failed to initialize GLFW!" << endl;
return false;
}
else
{
cout << "INITIALIZER: GLFW Initialized successfully!" << endl;
}
// Create window
/*!
* When this is called, or any other glfw functions, I get a
* "65537 The GLFW library is not initialized" in the console, through
* the error_callback function
*/
window = glfwCreateWindow( 800,
600,
"GLFW Window",
NULL,
NULL );
if( !window )
{
cout << "INITIALIZER: Failed to create window!" << endl;
glfwTerminate();
return false;
}
// Set window to current context
glfwMakeContextCurrent( window );
...
return true;
}
And here's what's printed out in the console
INITIALIZER: GLFW Initialized succesfully!
65537 The GLFW library is not initialized
INITIALIZER: Failed to create window!
I think I'm getting the error because of the setup isn't entirely correct, but I've done the best I can with what I could find around the place
I downloaded the windows 32 from glfw.org and stuck the 2 includes files from it into minGW/include/GLFW, the 2 .a files (from the lib-mingw folder) into minGW/lib and the dll, also from the lib-mingw folder, into Windows/System32
In code::blocks I have, from build options -> linker settings, linked the 2 .a files from the download. I believe I need to link more things, but I can figure out what, or where I should get those things from.
I tried reinstalling codeblocks and mingw, which solved the issue.
Seems like GLFW3 doesn't like having previous versions installed at the same time for some reason, so if anyone else is having a similar problem, you might want to try that.
I experienced similar problems in Cocos 3.8.1 and 3.10.
I have never installed codeblocks or mingw, so it did not make sense to install them for me.
The GLFW.lib file in the cocos directory is out of date.
http://www.glfw.org/download.html, and replace the lib file in your project with the latest one, and it may resolve your error.