Can't get different compilers to use specific header files? - c

I'm writing a C project for college, and I want to use the Sleep() function in my header file. The people marking it could be using Linux and I'm developing in VS2013 for Windows. I found out that Sleep() exists in two different header files depending on whether the compiler uses Windows or Linux, I've looked over the web and found suggestions to use "#ifdef" in the preprocessor. However I'm new to preprocessor work so I'm not sure what to use when there's many different suggestions out there, I'm particularly unsure as to whether these suggestions are for the same purpose as mine, so apologies if this is a common question. I've tried the following:
#ifdef _WIN32 || _WIN64
#include<windows.h>
#elif __linux
#include<unistd.h>
#else
#include<unistd.h>
#endif
This compiles fine in VS2013 but I get errors on a linux machine for Sleep() so the code I'm using doesn't seem to work outside of VS2013. Could someone explain what needs to be specified in order to get Windows and Linux to use their respective headers?

The Linux function is named sleep(), in lowercase, but the Windows one is Sleep(), with an uppercase S. And C is case-sensitive. Moreover, the Windows Sleep() takes the argument as milliseconds while the Linux alternative uses seconds.
So something like this is required:
#ifdef _WIN32 || _WIN64
#include<windows.h>
#define sleep(x) Sleep((x) * 1000)
#elif __linux
#include<unistd.h>
#else
#include<unistd.h>
#endif
Or if you prefer, you can do the other way around, but you'll have precision issues. (Consider using nanosleep() if that's an issue).

Related

checking whether library exist via preprocessor

There are two libraries zconf.h and unistd.h which are used to at least to get pid of the process. I generally test my code on Mac OSX and Ubuntu 18.04 in which they use zconf.h preferably(compiler offers zconf.h in lieu of unistd.h) if I forget to add, then if the code works, it's ok. However, in some prior day I needed to test the code in another machine AFAIR it has Ubuntu 10 or 12. Its compiler complained that there is no zconf.h. I wonder whether there is a way to check a machine has zconf.h, if not, use unistd.h. Can it be done using preprocessors like,
#ifdef ITS_IF_CONDITION
#include <zconf.h>
#else
#include <unistd.h>
Newer versions of GCC, clang and MSVC compilers implement the __has_include feature. Although it's a C++ 17 feature, I believe all three support it in plain C too.
But the traditional (and probably more portable) way is to check the existence of include files in a config script before the build process. Both autoconf and cmake have ways to achieve this.
#ifdef __has_include
#if __has_include(<zconf.h>)
#include <zconf.h>
#else
#include <unistd.h>
#endif
#else
#include <unistd.h>
#endif

portable alternative to kbhit() and getch() and system("cls")

I need a way to use kbhit and getch functionality in a portable way. I'm currently developing a simple ascii game and I need to detect if a key is pressed. If it is I need to read it and if it isn't I need to continue without waiting for input. I would prefer not to echo it, but I won't be to picky about that. I think kbhit and getch would be great for this, BUT I'm only allowed to use fully portable code(well at least code for linux, mac and PC, not a lot of other OSes come to mind though). As I understand it the termios, curses, and conio libraries aren't fully implemented on all three OSes I need. I'm at a loss. Every solution I have found uses non-portable code. Is there someway I'm able to write portable functions for this myself? I'm currently including stdio.h, stdlib.h, and time.h. I also need a portable way to clear the screen as I'm currently using system("cls") and system("clear") which must also be changed every time I change the OS, or is the a way I could do an if-else and detect the OS the code is running on to switch between these two statements. Here is a segment of code that has these functions:
char key = ' ';
while(1)
{
system("cls");
if (_kbhit())
{
key =_getch();
printf("output: %c", key);
}
else
printf("output:");
}
This is essentially what functionality I need in my code, but I can't figure out a portable way to do it, and my teacher requires the code to work on Linux, mac, and pc using standard c and standard libraries. Please help! And no c++ please, we are using c.
EDIT: I don't think ncurses wasn't quite what I was looking for. Someone recommended I use #ifdef to implement these at compile time. I like this solution, but I need some help understanding how to do this on linux and mac as I can only test on windows with my current setup. hopefully I will soon have linux running on my other machine for testing, but OSX has a big price tag with it, so I would appreciate the help. Here's the current code:
//libraries
#include <stdio.h> //used for i/o
#include <stdlib.h> //used for clearing the screen
#include <time.h> //used to get time for random number generator
//check OS and include necessary libraries
#ifdef _WIN32
//code for Windows (32-bit and 64-bit, this part is common)
#include <conio.h>
#define CLEARSCREEN system("cls")
#define CHECKKEY _kbhit()
#define NBGETCHAR getch()
#elif __APPLE__
//code for mac
#define CLEARSCREEN system("clear")
#define CHECKKEY
#define NBGETCHAR
#elif __linux__
//code for linux
#define CLEARSCREEN system("clear")
#define CHECKKEY
#define NBGETCHAR
#else
# error "Unknown compiler"
#endif
int main()
{
char key = ' ';
while(1)
{
CLEARSCREEN;
if (CHECKKEY)
{
key=NBGETCHAR;
printf("output: %c", key);
}
else
printf("output:");
}
}
You should look into the portable ncurses library. In addition to many other tools for drawing in the terminal, it provides a keyboard interface which includes a getch() function.

Compiler ignores #define _GNU_SOURCE

I am not a native english speaker, so please excuse any spelling or grammar mistakes
I am not a compiling expert, nor do I have any useful experience with builds and their errors
I am C# programmer and mainly working in an MS Enviroment
I only know the 3 "must know to survive in Linux commands" "./configure, make & make install" from my little Linux Experience
My Development Enviroment
I am using a Windows 7 Workstation
with Cygwin and MinGW (as Linux 'Replacement') to compile.
The Problem
I want to compile C source code on windows, which is primary written for Linux distributions.
/Configure works without problems.
If I use the command make to compile the sources, I run into following error:
Error
grib_keys.c:50:34:
error: 'alphasort' undeclared (first use in this function)
Research:
My Research proved me, that this problem already has been solved, but unfortunately, the answer isn't working for me.
Implicit declaration of scandir; alphasort is undeclared
http://ubuntuforums.org/archive/index.php/t-1653576.html
The solution says, that I only have to include following: #define _GNU_SOURCE
Which I tried, but as already stated, it doesn't work.
I included it in following files:
- grib_keys.c
- config.h
and tried to compile them with concurrent and not concurrent inclusion.
In the end, the important parts of the files looked like this:
config.h
********
/* Add #define _GNU_SOURCE to solve "'alphasort' undeclared" error */
#define _GNU_SOURCE
grib_keys.c
***********
#define _GNU_SOURCE
count = scandir(dir, &files, 0, alphasort);
What I want to achive & to know:
I want to compile the whole sourcecode of below named API, to use the binaries on a windows operating system.
Also I would like to know, whether I wrote the "#define _GNU_SOURCE"-Tag to the right place, or if I made a mistake.
Downloads:
Api
https://software.ecmwf.int/wiki/display/GRIB/Home
If you're going to declare feature-test macros such as _GNU_SOURCE, you must ensure that the preprocessor sees them before it sees any code that uses them. That generally means they have to be processed before any system headers. The best placement, therefore, is at the top of each of your C source files (not headers), before any #include directives.
With that said, you need a solution that applies to the C library you're actually using, and its development headers. For MinGW, it seems that would be Microsoft's C library, which does not appear to document an alphasort() function.
Even if you were using glibc (Cygwin's version, for instance) my glibc docs claim that the needed feature-test macro for alphasort() is either _BSD_SOURCE or _SVID_SOURCE, not _GNU_SOURCE. Since glibc 2.10, it looks like it's probably best to use _POSIX_C_SOURCE >= 200809L, or _XOPEN_SOURCE >= 700, as these reflect the fact that the function was standardized in POSIX.1-2008.

Most standard way to select a function name depending on platform?

I am currently using the popen function in code that is compiled by two compilers: MS Visual Studio and gcc (on linux). I might want to add gcc (on MinGW) later.
The function is called popen for gcc, but _popen for MSVS, so i added the following to my source code:
#ifdef _MSC_VER
#define popen _popen
#define pclose _pclose
#endif
This works, but i would like to understand whether there exists a standard solution for such problems (i recall a similar case with stricmp/strcasecmp). Specifically, i would like to understand the following:
Is _MSC_VER the right flag to depend on? I chose it because i have the impression that linux environment is "more standard".
If i put these #define's in some header file, is it important whether i #include it before or after stdio.h (for the case of popen)?
If _popen is defined as a macro itself, is there a chance my #define will fail? Should i use a "new" token like my_popen instead, for that reason or another?
Did someone already do this job for me and made a good "portability header" file that i can use?
Anything else i should be aware of?
Better to check for a windows-specific define (_WIN32 perhaps) because mingw won't have it either. popen() is standardised (it's a part of the Single UNIX® Specification v2)
No; so long as the macro is defined before its first use it does not matter if _popen() is not defined until later.
No; what you have is fine even if _popen is a macro.
It's been done many times but I don't know of a freely-licensed version you can use.
The way you are doing it is fine (with the #ifdef etc) but the macro that you test isn't. popen is something that depends on your operating system and not your compiler.
I'd go for something like
#if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 2)
/* system has popen as expected */
#elif defined(YOUR_MACRO_TO DETECT_YOUR_OS)
# define popen _popen
# define pclose _pclose
#elif defined(YOUR_MACRO_TO DETECT_ANOTHER_ONE)
# define popen _pOpenOrSo
# define pclose _pclos
#else
# error "no popen, we don't know what to do"
#endif
_MSC_VER is the correct macro for detecting the MSVC compiler. You can use __GNUC__ for GCC.
If you are going to use popen as your macro ID, I suggest you #include it after, because of 3.
If you #include it after stdio.h, it should work AFAIK, but better safe than sorry, no? Call it portable_popen or something.
Many projects (including some of mine) have a portability header, but it's usually better to roll your own. I'm a fan of doing things yourself if you have the time. Thus you know the details of your code (easier to debug if things go wrong), and you get code that is tailored to your needs.
Not that I know of. I do stuff like this all the time, without problems.
Instead of ending up with cluttered files containing #ifdef..#else..#endif blocks, I'd prefer a version using different files for different platforms:
put the OS dependent definitions in one file per platform and #define a macro my_popen
#include this file in your platform-agnostic code
never call the OS functions directly, but the #define that you created (i.e. my_popen)
depending on your OS, use different headers for compilation (e.g. config/windows/mydefines.h on windows and config/linux/mydefines.h on linux, so set the include path appropriate and always #include "mydefines.h")
That's a much cleaner approach than having the OS decision in the source itself.
If the methods you're calling behave different between windows and linux, decide which one shall be the behavior you're using (i.e. either always windows behavior or always linux behavior) and then create wrapper methods to achieve this. For that, you'll also need not only two mydefines.h files but also to myfunctions.c files that reside in the config/OSTYPE directories.
Doing it that way, you also get advantages when it comes to diff the linux and the windows version: you could simply diff two files while doing a diff on the linux and windows blocks of the same file could be difficult.

Link User32 with gcc

I have a C program which has a function call that is defined in windows.h (which I have included), however, when I try and compile it with gcc, I get the error:
warning: implicit declaration of function `LockWorkStation'
I looked at the MSDN documentation and I see that this function is the User32 library file, and I was wondering how I would go about linking that to my file.
LockWorkstation is available on Windows 2000 and up. You have to declare the version of Windows you are targeting. Make it look like this:
#define _WIN32_WINNT 0x500
#include <windows.h>
I have the same problem with gcc - but this is not a linker error. The message means that there is no prototype for the function in winuser.h, or more accurately the compiler can't find such a prototype. That is because the relevant bit of winuser.h looks like this:
#if (_WIN32_WINNT >= 0x0500)
WINUSERAPI BOOL WINAPI LockWorkStation(void);
#endif
In other words, you need a version of Windows >= 5 (i.e Win2K) to use this function. I'm currently trying this on Win2K and it doesn't work, which indicates the macro is not being set correctly. I don't do much "real" Windows programming these days, so I'm not sure why that should be.
Edit: In fact, a bit of experiment indicates that gcc thinks the Windows version of Win2K (on my installation at least) is 0x0400.
Further: Actually, the macro _WIN32_WINNT is (as the leading underscore suggests) a reserved name in C and C++, and should not be defined in user code. Defining the macro WINVER seems to have the same effect, and is (conceptually at least) more portable. This code compiles on my gcc installation:
#define WINVER 0x0500
#include <windows.h>
int main() {
LockWorkStation();
}

Resources