How to avoid specific #ifdef in multi - platform qt code?
I have a QT input listener class, that signals stdin
inputs in a running QCoreApplication
. I want to use that on both windows and linux.
My current approach is to use #ifdef Q_OS_WIN
inside both header and cpp to execute the platform-specific code. As I know, that #ifdef
is considered harmful and should be avoided, I want to refactor this in a manner where I have one single header file inputlistener.h
and let the build system choose between a specific windows/inputlistener.cpp
or linux/inputlistener.cpp
, maybe with an additional inputlistener_global.cpp
that holds the code, which is not platform specific.
However, I can't find a solution, how to get the #ifdef
in the header out of the way.
How can I achieve that?
Here is my current approach:
#inputlistener.h
#ifndef INPUTLISTENER_H
#define INPUTLISTENER_H
#include <QtCore>
class inputlistener : public QObject {
Q_OBJECT
private:
#ifdef Q_OS_WIN
QWinEventNotifier* m_notifier;
#else
QSocketNotifier* m_notifier;
#endif
signals:
void inputeventhappened(int keycode);
private slots:
void readyRead();
public:
inputlistener();
};
#endif // INPUTLISTENER_H
#inputlistener.cpp
#include "inputlistener.h"
#include "curses.h"
#ifdef Q_OS_WIN
#include <windows.h>
#endif
inputlistener::inputlistener()
{
#ifdef Q_OS_WIN
m_notifier = new QWinEventNotifier(GetStdHandle(STD_INPUT_HANDLE));
connect(m_notifier, &QWinEventNotifier::activated
#else
m_notifier = new QSocketNotifier(0, QSocketNotifier::Read, this);
connect(m_notifier, &QSocketNotifier::activated
#endif
,
this, &inputlistener::readyRead);
readyRead(); // data might be already available without notification
}
void inputlistener::readyRead()
{
// It's OK to call this with no data available to be read.
int c;
while ((c = getch()) != ERR) {
emit inputeventhappened(c);
}
}
c++ qt cross-platform multiplatform
add a comment |
I have a QT input listener class, that signals stdin
inputs in a running QCoreApplication
. I want to use that on both windows and linux.
My current approach is to use #ifdef Q_OS_WIN
inside both header and cpp to execute the platform-specific code. As I know, that #ifdef
is considered harmful and should be avoided, I want to refactor this in a manner where I have one single header file inputlistener.h
and let the build system choose between a specific windows/inputlistener.cpp
or linux/inputlistener.cpp
, maybe with an additional inputlistener_global.cpp
that holds the code, which is not platform specific.
However, I can't find a solution, how to get the #ifdef
in the header out of the way.
How can I achieve that?
Here is my current approach:
#inputlistener.h
#ifndef INPUTLISTENER_H
#define INPUTLISTENER_H
#include <QtCore>
class inputlistener : public QObject {
Q_OBJECT
private:
#ifdef Q_OS_WIN
QWinEventNotifier* m_notifier;
#else
QSocketNotifier* m_notifier;
#endif
signals:
void inputeventhappened(int keycode);
private slots:
void readyRead();
public:
inputlistener();
};
#endif // INPUTLISTENER_H
#inputlistener.cpp
#include "inputlistener.h"
#include "curses.h"
#ifdef Q_OS_WIN
#include <windows.h>
#endif
inputlistener::inputlistener()
{
#ifdef Q_OS_WIN
m_notifier = new QWinEventNotifier(GetStdHandle(STD_INPUT_HANDLE));
connect(m_notifier, &QWinEventNotifier::activated
#else
m_notifier = new QSocketNotifier(0, QSocketNotifier::Read, this);
connect(m_notifier, &QSocketNotifier::activated
#endif
,
this, &inputlistener::readyRead);
readyRead(); // data might be already available without notification
}
void inputlistener::readyRead()
{
// It's OK to call this with no data available to be read.
int c;
while ((c = getch()) != ERR) {
emit inputeventhappened(c);
}
}
c++ qt cross-platform multiplatform
1
It's not true that "#ifdef
is harmful". It's a matter of taste and depends on the particular application and situation. I wouldn't worry about this unless it's causing a real problem. You're gonna blow up your code in size just for some dogma.
– The Quantum Physicist
Nov 22 at 14:40
add a comment |
I have a QT input listener class, that signals stdin
inputs in a running QCoreApplication
. I want to use that on both windows and linux.
My current approach is to use #ifdef Q_OS_WIN
inside both header and cpp to execute the platform-specific code. As I know, that #ifdef
is considered harmful and should be avoided, I want to refactor this in a manner where I have one single header file inputlistener.h
and let the build system choose between a specific windows/inputlistener.cpp
or linux/inputlistener.cpp
, maybe with an additional inputlistener_global.cpp
that holds the code, which is not platform specific.
However, I can't find a solution, how to get the #ifdef
in the header out of the way.
How can I achieve that?
Here is my current approach:
#inputlistener.h
#ifndef INPUTLISTENER_H
#define INPUTLISTENER_H
#include <QtCore>
class inputlistener : public QObject {
Q_OBJECT
private:
#ifdef Q_OS_WIN
QWinEventNotifier* m_notifier;
#else
QSocketNotifier* m_notifier;
#endif
signals:
void inputeventhappened(int keycode);
private slots:
void readyRead();
public:
inputlistener();
};
#endif // INPUTLISTENER_H
#inputlistener.cpp
#include "inputlistener.h"
#include "curses.h"
#ifdef Q_OS_WIN
#include <windows.h>
#endif
inputlistener::inputlistener()
{
#ifdef Q_OS_WIN
m_notifier = new QWinEventNotifier(GetStdHandle(STD_INPUT_HANDLE));
connect(m_notifier, &QWinEventNotifier::activated
#else
m_notifier = new QSocketNotifier(0, QSocketNotifier::Read, this);
connect(m_notifier, &QSocketNotifier::activated
#endif
,
this, &inputlistener::readyRead);
readyRead(); // data might be already available without notification
}
void inputlistener::readyRead()
{
// It's OK to call this with no data available to be read.
int c;
while ((c = getch()) != ERR) {
emit inputeventhappened(c);
}
}
c++ qt cross-platform multiplatform
I have a QT input listener class, that signals stdin
inputs in a running QCoreApplication
. I want to use that on both windows and linux.
My current approach is to use #ifdef Q_OS_WIN
inside both header and cpp to execute the platform-specific code. As I know, that #ifdef
is considered harmful and should be avoided, I want to refactor this in a manner where I have one single header file inputlistener.h
and let the build system choose between a specific windows/inputlistener.cpp
or linux/inputlistener.cpp
, maybe with an additional inputlistener_global.cpp
that holds the code, which is not platform specific.
However, I can't find a solution, how to get the #ifdef
in the header out of the way.
How can I achieve that?
Here is my current approach:
#inputlistener.h
#ifndef INPUTLISTENER_H
#define INPUTLISTENER_H
#include <QtCore>
class inputlistener : public QObject {
Q_OBJECT
private:
#ifdef Q_OS_WIN
QWinEventNotifier* m_notifier;
#else
QSocketNotifier* m_notifier;
#endif
signals:
void inputeventhappened(int keycode);
private slots:
void readyRead();
public:
inputlistener();
};
#endif // INPUTLISTENER_H
#inputlistener.cpp
#include "inputlistener.h"
#include "curses.h"
#ifdef Q_OS_WIN
#include <windows.h>
#endif
inputlistener::inputlistener()
{
#ifdef Q_OS_WIN
m_notifier = new QWinEventNotifier(GetStdHandle(STD_INPUT_HANDLE));
connect(m_notifier, &QWinEventNotifier::activated
#else
m_notifier = new QSocketNotifier(0, QSocketNotifier::Read, this);
connect(m_notifier, &QSocketNotifier::activated
#endif
,
this, &inputlistener::readyRead);
readyRead(); // data might be already available without notification
}
void inputlistener::readyRead()
{
// It's OK to call this with no data available to be read.
int c;
while ((c = getch()) != ERR) {
emit inputeventhappened(c);
}
}
c++ qt cross-platform multiplatform
c++ qt cross-platform multiplatform
asked Nov 22 at 14:24
devjb
979
979
1
It's not true that "#ifdef
is harmful". It's a matter of taste and depends on the particular application and situation. I wouldn't worry about this unless it's causing a real problem. You're gonna blow up your code in size just for some dogma.
– The Quantum Physicist
Nov 22 at 14:40
add a comment |
1
It's not true that "#ifdef
is harmful". It's a matter of taste and depends on the particular application and situation. I wouldn't worry about this unless it's causing a real problem. You're gonna blow up your code in size just for some dogma.
– The Quantum Physicist
Nov 22 at 14:40
1
1
It's not true that "
#ifdef
is harmful". It's a matter of taste and depends on the particular application and situation. I wouldn't worry about this unless it's causing a real problem. You're gonna blow up your code in size just for some dogma.– The Quantum Physicist
Nov 22 at 14:40
It's not true that "
#ifdef
is harmful". It's a matter of taste and depends on the particular application and situation. I wouldn't worry about this unless it's causing a real problem. You're gonna blow up your code in size just for some dogma.– The Quantum Physicist
Nov 22 at 14:40
add a comment |
2 Answers
2
active
oldest
votes
You can create WinEventListener
and UnixEventListener
(or something else) each using it's own implementation (instead of trying to fit it into one via ifdefs), each implementing common Listener
interface (and residing in separate files).
Then, have a factory function that'd return listener appropriate to OS. That they there would be only one single place that might require ifdefs.
But in general, ifdef
ing something might be the best or the only course of action (e.g. when you already abstracting something). Conditional compilation is one of the few valid/justified usages of preprocessor (it's what it was made for).
Also, in your particular case, be sure there is not already appropriate code/class in Qt lib. For most common stuff chances are there is already existing abstraction (or recommended ways to do that).
add a comment |
You can create separate EventListener.cpp
files for windows
and unix
and put these files into subdirectories like (win
, linux
). To the makefile or to the projectfile you can add one implementation file based on the current platform. The compiler will compile just one file for the current platform.
With this method you can avoid ifdef
ing totally.
If the definitions are different you can use pImpl
idiom to separate the implementation details of a class: https://cpppatterns.com/patterns/pimpl.html
That'd be just moving "ifdefs" up the chain into the project file. Not that it's somehow worse or better.
– Dan M.
Nov 22 at 15:00
I wanted to separate the implementations. Im aware that this is a valid approach. But I am concerned about the header because the definitions are different, too, not only the implementations.
– devjb
Nov 22 at 15:36
If the definitions are different you can usepImpl
idiom to separate the implementation details of a class: cpppatterns.com/patterns/pimpl.html
– Peter
Nov 22 at 22:01
@devjb: I've put this extension into the answer.
– Peter
Nov 23 at 9:25
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53433029%2fhow-to-avoid-specific-ifdef-in-multi-platform-qt-code%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
You can create WinEventListener
and UnixEventListener
(or something else) each using it's own implementation (instead of trying to fit it into one via ifdefs), each implementing common Listener
interface (and residing in separate files).
Then, have a factory function that'd return listener appropriate to OS. That they there would be only one single place that might require ifdefs.
But in general, ifdef
ing something might be the best or the only course of action (e.g. when you already abstracting something). Conditional compilation is one of the few valid/justified usages of preprocessor (it's what it was made for).
Also, in your particular case, be sure there is not already appropriate code/class in Qt lib. For most common stuff chances are there is already existing abstraction (or recommended ways to do that).
add a comment |
You can create WinEventListener
and UnixEventListener
(or something else) each using it's own implementation (instead of trying to fit it into one via ifdefs), each implementing common Listener
interface (and residing in separate files).
Then, have a factory function that'd return listener appropriate to OS. That they there would be only one single place that might require ifdefs.
But in general, ifdef
ing something might be the best or the only course of action (e.g. when you already abstracting something). Conditional compilation is one of the few valid/justified usages of preprocessor (it's what it was made for).
Also, in your particular case, be sure there is not already appropriate code/class in Qt lib. For most common stuff chances are there is already existing abstraction (or recommended ways to do that).
add a comment |
You can create WinEventListener
and UnixEventListener
(or something else) each using it's own implementation (instead of trying to fit it into one via ifdefs), each implementing common Listener
interface (and residing in separate files).
Then, have a factory function that'd return listener appropriate to OS. That they there would be only one single place that might require ifdefs.
But in general, ifdef
ing something might be the best or the only course of action (e.g. when you already abstracting something). Conditional compilation is one of the few valid/justified usages of preprocessor (it's what it was made for).
Also, in your particular case, be sure there is not already appropriate code/class in Qt lib. For most common stuff chances are there is already existing abstraction (or recommended ways to do that).
You can create WinEventListener
and UnixEventListener
(or something else) each using it's own implementation (instead of trying to fit it into one via ifdefs), each implementing common Listener
interface (and residing in separate files).
Then, have a factory function that'd return listener appropriate to OS. That they there would be only one single place that might require ifdefs.
But in general, ifdef
ing something might be the best or the only course of action (e.g. when you already abstracting something). Conditional compilation is one of the few valid/justified usages of preprocessor (it's what it was made for).
Also, in your particular case, be sure there is not already appropriate code/class in Qt lib. For most common stuff chances are there is already existing abstraction (or recommended ways to do that).
edited Nov 22 at 14:35
answered Nov 22 at 14:29
Dan M.
1,94011123
1,94011123
add a comment |
add a comment |
You can create separate EventListener.cpp
files for windows
and unix
and put these files into subdirectories like (win
, linux
). To the makefile or to the projectfile you can add one implementation file based on the current platform. The compiler will compile just one file for the current platform.
With this method you can avoid ifdef
ing totally.
If the definitions are different you can use pImpl
idiom to separate the implementation details of a class: https://cpppatterns.com/patterns/pimpl.html
That'd be just moving "ifdefs" up the chain into the project file. Not that it's somehow worse or better.
– Dan M.
Nov 22 at 15:00
I wanted to separate the implementations. Im aware that this is a valid approach. But I am concerned about the header because the definitions are different, too, not only the implementations.
– devjb
Nov 22 at 15:36
If the definitions are different you can usepImpl
idiom to separate the implementation details of a class: cpppatterns.com/patterns/pimpl.html
– Peter
Nov 22 at 22:01
@devjb: I've put this extension into the answer.
– Peter
Nov 23 at 9:25
add a comment |
You can create separate EventListener.cpp
files for windows
and unix
and put these files into subdirectories like (win
, linux
). To the makefile or to the projectfile you can add one implementation file based on the current platform. The compiler will compile just one file for the current platform.
With this method you can avoid ifdef
ing totally.
If the definitions are different you can use pImpl
idiom to separate the implementation details of a class: https://cpppatterns.com/patterns/pimpl.html
That'd be just moving "ifdefs" up the chain into the project file. Not that it's somehow worse or better.
– Dan M.
Nov 22 at 15:00
I wanted to separate the implementations. Im aware that this is a valid approach. But I am concerned about the header because the definitions are different, too, not only the implementations.
– devjb
Nov 22 at 15:36
If the definitions are different you can usepImpl
idiom to separate the implementation details of a class: cpppatterns.com/patterns/pimpl.html
– Peter
Nov 22 at 22:01
@devjb: I've put this extension into the answer.
– Peter
Nov 23 at 9:25
add a comment |
You can create separate EventListener.cpp
files for windows
and unix
and put these files into subdirectories like (win
, linux
). To the makefile or to the projectfile you can add one implementation file based on the current platform. The compiler will compile just one file for the current platform.
With this method you can avoid ifdef
ing totally.
If the definitions are different you can use pImpl
idiom to separate the implementation details of a class: https://cpppatterns.com/patterns/pimpl.html
You can create separate EventListener.cpp
files for windows
and unix
and put these files into subdirectories like (win
, linux
). To the makefile or to the projectfile you can add one implementation file based on the current platform. The compiler will compile just one file for the current platform.
With this method you can avoid ifdef
ing totally.
If the definitions are different you can use pImpl
idiom to separate the implementation details of a class: https://cpppatterns.com/patterns/pimpl.html
edited Nov 23 at 9:24
answered Nov 22 at 14:53
Peter
62618
62618
That'd be just moving "ifdefs" up the chain into the project file. Not that it's somehow worse or better.
– Dan M.
Nov 22 at 15:00
I wanted to separate the implementations. Im aware that this is a valid approach. But I am concerned about the header because the definitions are different, too, not only the implementations.
– devjb
Nov 22 at 15:36
If the definitions are different you can usepImpl
idiom to separate the implementation details of a class: cpppatterns.com/patterns/pimpl.html
– Peter
Nov 22 at 22:01
@devjb: I've put this extension into the answer.
– Peter
Nov 23 at 9:25
add a comment |
That'd be just moving "ifdefs" up the chain into the project file. Not that it's somehow worse or better.
– Dan M.
Nov 22 at 15:00
I wanted to separate the implementations. Im aware that this is a valid approach. But I am concerned about the header because the definitions are different, too, not only the implementations.
– devjb
Nov 22 at 15:36
If the definitions are different you can usepImpl
idiom to separate the implementation details of a class: cpppatterns.com/patterns/pimpl.html
– Peter
Nov 22 at 22:01
@devjb: I've put this extension into the answer.
– Peter
Nov 23 at 9:25
That'd be just moving "ifdefs" up the chain into the project file. Not that it's somehow worse or better.
– Dan M.
Nov 22 at 15:00
That'd be just moving "ifdefs" up the chain into the project file. Not that it's somehow worse or better.
– Dan M.
Nov 22 at 15:00
I wanted to separate the implementations. Im aware that this is a valid approach. But I am concerned about the header because the definitions are different, too, not only the implementations.
– devjb
Nov 22 at 15:36
I wanted to separate the implementations. Im aware that this is a valid approach. But I am concerned about the header because the definitions are different, too, not only the implementations.
– devjb
Nov 22 at 15:36
If the definitions are different you can use
pImpl
idiom to separate the implementation details of a class: cpppatterns.com/patterns/pimpl.html– Peter
Nov 22 at 22:01
If the definitions are different you can use
pImpl
idiom to separate the implementation details of a class: cpppatterns.com/patterns/pimpl.html– Peter
Nov 22 at 22:01
@devjb: I've put this extension into the answer.
– Peter
Nov 23 at 9:25
@devjb: I've put this extension into the answer.
– Peter
Nov 23 at 9:25
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53433029%2fhow-to-avoid-specific-ifdef-in-multi-platform-qt-code%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
It's not true that "
#ifdef
is harmful". It's a matter of taste and depends on the particular application and situation. I wouldn't worry about this unless it's causing a real problem. You're gonna blow up your code in size just for some dogma.– The Quantum Physicist
Nov 22 at 14:40