Use a self-made C function in QT
-
Hello ! I'm currently doing a menu for a raytracer. My raytracer have features that change colors and effect, i want to add buttons on my menu that apply the effect directly !
Let's use for example the effect black and white, i got my fonction declared like this : b_and_w(t_env *e)
t_env is just a simple struct containing few variables.After few researches i found out i got to use extern "C" {}, so i declared my function in qt like this :
#ifdef __cplusplus extern "C" { #endif ... INCLUDES ... void b_and_w(t_env *e) { ... MYCODE ... } #ifdef __cplusplus } #endif
Qt seems fine with it, but now i want to call it when button is clicked so i did this :
QObject::connect(b_effect, SIGNAL(clicked()), this, SLOT(b_and_w(e)));
Of course, as i expected, Qt doesn't know what "e" is... So here i am, totally stuck, not managing to call my function when needed :/
-
You cannot use simple C functions as slots for signals. You need to have a class derived from QObject which holds also the Q_OBJECT macro. Please have a look to signals and slots.
Also it is always a good choice to familiarize with some of the examples. Sometimes you find one which resembles closely what you like to achieve. So you might have a good jumpstart and you can divert from there.
If you like to use Qt C is not sufficient enough and you have to understand some of the basics of C++.
-
@koahnig said in Use a self-made C function in QT:
You cannot use simple C functions as slots for signals.
Sure you can, example:
void aboutToQuitHandler() { } int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); QObject::connect(&app, &QCoreApplication::aboutToQuit, aboutToQuitHandler); QTimer::singleShot(0, &app, &QCoreApplication::quit); return app.exec(); }
Lambdas are (almost) quite the same as a plain C functions.
@EL_Mambo said in Use a self-made C function in QT:
Of course, as i expected, Qt doesn't know what "e" is... So here i am, totally stuck, not managing to call my function when needed :/
Use the Qt 5 connection syntax and std::bind to bind the local variable as an argument to the slot. Also is there a specific reason to use
extern "C"
? If not then you should just remove it. -
Also is there a specific reason to use extern "C"? If not then you should just remove it.
If the function is implemented in a C file, then yes. Reason is the C++ compiler name mangling.
so extern C should stay.
-
@aha_1980 said in Use a self-made C function in QT:
Reason is the C++ compiler name mangling.
Which would be irrelevant if you don't intend to export the symbols with undecorated ABI, which is the "specific reason" I was asking about. (note that the linkage specifier is around the actual definition)
-
@EL_Mambo I was able to call a function contained in a .c file directly from the signal of a Qt widget using the new syntax of connecting signal to simple functions
function.h
#ifndef FUNCTION_H #define FUNCTION_H void b_and_w(); #endif // FUNCTION_H
function.c
#include "function.h" #include <stdio.h> void b_and_w() { fprintf(stderr, "C function called\n"); }
In mainwindow.cpp (MainWindow just contains a QPushButton called btnCallC)
... #ifdef __cplusplus extern "C" { #endif #include "function.h" #ifdef __cplusplus } #endif ... MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); connect(ui->btnCallC, &QPushButton::clicked, b_and_w); }
you may need to play a little bit to pass the struct you mentioned before. See @kshegunov suggestion about using std:bind
-
@kshegunov said in Use a self-made C function in QT:
@koahnig said in Use a self-made C function in QT:
You cannot use simple C functions as slots for signals.
Sure you can, example:
void aboutToQuitHandler() { } int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); QObject::connect(&app, &QCoreApplication::aboutToQuit, aboutToQuitHandler); QTimer::singleShot(0, &app, &QCoreApplication::quit); return app.exec(); }
Lambdas are (almost) quite the same as a plain C functions.
Oops, I admit that I was wrong here.
Anyway you are using a functor here.
Am I correct that you require the functor-type and cannot use the macro style as at top of post?
-
@koahnig said in Use a self-made C function in QT:
Am I correct that you require the functor-type and cannot use the macro style as at top of post?
Yes, you're right in that case and that's one of the benefits of the new syntax for signals & slots.
-
@koahnig said in Use a self-made C function in QT:
Anyway you are using a functor here.
A functor is a function with an object attached, so if you don't have data it is simply a function. :)
Am I correct that you require the functor-type and cannot use the macro style as at top of post?
Yes, Qt wraps the pointer you pass it in a special object (using some template black magic to get the arguments right) that it uses to actually execute it when needed. This will not work with the Qt4 syntax, as there the resolution is done in runtime through the meta-object system.
-
Hi,
In addition to what my fellow wrote: you can't connect a signal with fewer parameters than the slot you want to call unless it has default arguments. It's also not possible with the new syntax but you can use a lambda as an alternative.
-
@Pablo-J.-Rogina @kshegunov @SGaist
Well, at least I can use as excuse that I learnd signal-slot functionality way back with Qt 4.3 (probably?) and there was only the macro version possible. And apparently, I shall give up my stubbornness and finally stash or trash my Qt 5.4 version, which is still a bit restricted with functor-based syntax on connect. ;)