'windows.h', what about other platforms? - c++

I'm using visual studio on windows and I have this header file called windows.h which of course gives me access to the win32 API.
but when I try to use other platforms API like the linux API for example. I don't find any header file with that name, which mean that I can't use any other OS API than windows,
now the problem here is: what if I wan't to make a cross platform program for example ? when I don't have the appropriate access to its API, I tried to do some researches for a sometime but couldn't get any answer to my questions, which is really troubling my mind right now, so to be more specific these are my questions:
1- why I can only use the windows API out of all the other operating systems ?
is it because I'm coding on windows, so if I was coding "somewhere else" it would be different ?
or is it something related to the compiler itself ?
2- what if I want to use another API do I have to use an external library ? and if that's the case how is the Standard Library in c++ cross platform, I mean if it is cross platform then there should exist other platform specific headers provided by the library right ?

I'm using visual studio on windows and I have this header file called windows.h which of course gives me access to the win32 API.
Strictly speaking windows.h is sort of a meta-header. Some important macros, tokens and symbols are defined in windows.h, but it also pulls in a lot of other headers. If you look at the reference manual of each of the Win32 API functions it will tell you there, which header that function is declared in. Let's have a look at CreateFileA for example: At the bottom of the reference manual you'll find:
Requirements
Minimum supported client Windows XP [desktop apps only]
Minimum supported server Windows Server 2003 [desktop apps onliy]
Target Platform Windows
Header fileapi.h (include Windows.h)
Library Kernel32.lib
DLL Kernel32.dll
So this tells us, that CreateFileA actually is declared in fileapi.h and is exported from the kernel32.dll system library.
but when I try to use other platforms API like the linux API for
example.
That is, because there is no linux.h API header (if you search a Linux development system for files named linux.h you'll find plenty, but those are not used for the system level API).
The reason for that is, that Linux doesn't have its very own, proprietary API, but folloes the POSIX industry standard for operating system APIs, and the Single Unix Specification maintained by the Open Group.
There are of course Linux specific APIs, but you can safely ignore them for "usual" application development; you need those if you're doing low level stuff, like writing a C runtime library, or custom memory allocators.
Of most interest for you, as a developer are the manpages in section 2 (calls into the operating system kernel = syscalls) and section 3 (library functions). https://linux.die.net/man/
The POSIX equivalent to CreateFileA would be open which you can find in section 2: https://linux.die.net/man/2/open (or the creat syscall, that exists for legacy reasons, but nobody uses that (or should use it)).
If you look at the manpage of open it tells you
open(2) - Linux man page
Name
open, creat - open and possibly create a file or device
Synopsis
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
int creat(const char *pathname, mode_t mode);
That tells you, that in order to use open you need to include sys/types.h, sys/stat.h and fcntl.h. Unlike Windows there's no all overencompassing header that pulls in everything. The reason for this is, that for backwards and cross compatibility reasons the things that are exposed by a header can be configured by setting certain macros to specific values before including the header. Those are explained in feature_test_macros(7), and for functions where they apply these are also mentioned in the respective manual page.
I don't find any header file with that name, which mean that
I can't use any other OS API than windows,
Just because you can't find it, doesn't mean it doesn't exist.
now the problem here is: what if I wan't to make a cross platform program for example?
Then you write all the platform specific things into a separate .c file, that encapsulates the OS stuff.
when I don't have the appropriate access to its API
Well, you do.
1- why I can only use the windows API out of all the other operating systems?
Because you can't. Windows.h is available only on Windows systems.
2- what if I want to use another API do I have to use an external library?
Then you just use it.
Keep in mind that in Linux the graphical environment is not part of the main operating system. It's in fact a regular program that is automatically launched on system start. Hence you won't find documentation for that in the aforementioned manpages.
The default graphics enviroment for Linux is Xorg (an open implementation of the X11 display system). There's also Wayland, but after over 10 years in development it's still poorly supported and leaves a lot to be desired.
If you want to program X11 on the same level as Win32, you'll have to deal with the Xlib or Xcb. However direct X11 programming is quite tedious. You probably want to use some nice application framework like Qt or GTK. Qt by itself is a cross platform framework, so if you limit yourself to use only, and only Qt functions, your program will be fully cross platform without extra effort. If you want to do 3D graphics on the GPU, use the cross platform APIs OpenGL or Vulkan.

but when I try to use other platforms API like the linux API for example. I don't find any header file with that name
There is no header called <linux> for the system API. The POSIX operating system specification (which Linux conforms to) lists several headers which contain the functionality that you might find from windows.h on that system. POSIX spec overlaps with the C standard library, and the C standard library implementation also provides the POSIX specific headers. See the Linux manual or POSIX spec for full list of headers.
what if I want to use another [system] API
You will need at least the header files of that API in order to compile programs that call them. Furthermore, you'll need the library archives in order to link your programs. And you'll need to tell the compiler which system you are targeting. By default, all compilers assume that you target the system that is running the compiler. You'll need to consult the documentation of your compiler about whether cross compilation is possible, and how to do it.
Or a simpler approach: Compile on the system where the API is provided. The headers may need to be installed separately.
... how is the Standard Library in c++ cross platform
Each system has their own standard library. Some of the implementations of standard library are cross platform, but not all. For example, the libstdc++ - which is the standard library that is part of the GNU project, and is the default standard library in Linux - is available on many platforms including Windows. By contrast, the Msvc standard library is only available on Windows.

The Wikipedia about windows.h library says:
windows.h is a Windows-specific header file for the C and C++
programming languages which contains declarations for all of the
functions in the Windows API, all the common macros used by Windows
programmers, and all the data types used by the various functions and
subsystems.
Linux doesn’t provide a default API for window management as does Windows so if you are programming a graphical application then you need to choose a windowing library as well.

The answer to part one is yes. You can only use the Windows API because you are programming on Windows. However you can run Linux on Windows. A Microsoft product called the Windows Subsystem for Linux allows you to do that. But even if you do that you won't find a header called linux.h, it's more complicated than that. There is also a product (called WINE I believe) that lets you use the Windows API on Linux, although I believe it has a few issues.
The standard library interface is cross platform, but it's implementation certainly isn't. It does this by abstracting away OS specific features. If you look at how the library is implemented on different platforms you will certainly see lots of differences.

Related

How to detect current operating system at runtime in c++?

I want to detect which operating system my .exe is being run on, so that I could perform specific operations depending on the underlying operating system. I want it to be just for windows and mac.
I want to detect which operating system my .exe is being run on
(notice that on MacOSX executable files are traditionally not suffixed with .exe; that convention is specific to Windows)
You cannot detect that in pure standard C++11 at runtime (so your question makes technically no sense), because the C++11 standard n3337 does not know about operating systems (some C++ source code may be compiled for the bare metal). I would recommend conditional compilation (e.g. #if) and using operating system specific headers (and configuring your build automation to detect them). Some C++ frameworks (boost, poco, Qt....) could be helpful, but you need to decide to choose one (they might try to provide some common abstractions above several OSes, but the evil is still in the details, e.g. file paths are still different on Windows and on MacOSX).
MicroSoft Windows has its own API, called WinAPI (which is only, in practice, used by Windows. Perhaps some day ReactOS would implement most of that API), documented here. MacOSX is more or less conforming to POSIX, which is a standard API about a family of OSes (but Windows don't care much about that standard).
If you want to learn more about OSes in general (a sensible thing to do), read for example Operating Systems: Three Easy Pieces (freely downloadable textbook).
In practice, an executable file compiled from C++ source code is specific to the operating system it is designed to run on, and its file format is also specific to some OS (e.g. PE on Windows, ELF on Linux, Mach-O on MacOSX...). So a Windows executable won't run on MacOSX and vice versa (the fat binary idea is out of fashion in 2018). You probably would adjust your build procedure (e.g. your Makefile, or with cmake, ninja, etc...) for your OS. That build procedure might (and often does) pass extra compilation flags (e.g. some -DBUILD_FOR_MACOSX compiler flag for your preprocessor, if building for MacOSX; then you might -in few places- use some preprocessor directive like #if BUILD_FOR_MACOSX in your C++ source code) specific to the target operating system. You could even customize your build so that on MacOSX some for-macosx.cc C++ file is compiled (and its object file linked into) your software, but on Windows you'll use some other for_windows.cc C++ file. Sometimes, the build procedure is flexible enough to auto-detect at build time what is the operating system (but how to do that is a different question. The GNU autoconf could be inspirational).
Once your build procedure has been configured for (or has auto-detected) your operating system, you could use preprocessor conditional facilities to #include appropriate system-specific headers and to compile calls to OS specific functions (such as POSIX uname) querying further at runtime about the OS.
Some compilers predefine a set of preprocessor symbols, and that set depends upon the target operating system and processor and of your compiler. If you use GCC, you might create some empty file empty.cc and compile it with g++ -c -C -E -dM (perhaps also with other relevant flags, e.g. -std=c++11) to find out which set of preprocessor symbols are predefined in your case.
Consider studying the source code (including the build procedure!) of some cross-platform free software projects (e.g. on github or somewhere else) for inspiration. You can also find many resources about multi-platform C++ builds (e.g. this one and many others).
There are various ways you could do it, like testing for the presence of a C:\Windows directory to detect Windows (edit: if the OS accepts a path like that at all then it's at least part of the DOS family), but none of them are foolproof. Here's one way (although it's cheating):
#include<boost/predef.h>
enum class OperatingSystem {
// ...
Windows
// ...
};
OperatingSystem DetectOperatingSystem()
{
#ifdef BOOST_OS_WINDOWS
return OperatingSystem::Windows;
#endif
}
Also, if you just want a name to show the user, then on POSIX systems you can use uname(2).
To solve this kind of problem you would need to check both at compile time and at run time. You are going to need different code for different both systems. You are going to need Windoze code to check the Windoze version and Mac code to check the Mac version.
You are going to have to use
#if defined ()
at compile time to check which of the two you are on. Then have separate code for each to get the version.

Program which Compile by Code::Block plus MinGW, but Using Standard Windows Library?

everyone.
I am a newer for c++, and I had some experience on c#. I want to create a pure c++ developing environment, and using the standard c++ library. My operation system is Windows.
I choose code::block+MinGW to build a pure developing environment on Windows. I directly choose Code::Block installation packet which integrate MinGW. Then I began to develop my first learning project. And In this project, I used the function "stat" to get file information from standard library. And I passed the compile. But during operation this program, I checked the "Call Stack". And found the function "stat" called from file "C:\WINDOWS\system32\msvcrt.dll". And I checked this dll from internet, and found this file is a microsoft windows library file. So it obviously, this dll file don't have the function "stat", but have the function "_stat".
So how do I solve this problem? I want to use the standard c++ library, not the microsoft windows library. Because later, I want to move this project to linux environment. So overall, how do I build the developing environment to satisfy my requirement.
You have to use the windows system libraries if you're building for Windows. You simply link one or the other depending on the target system. The libraries merely provide the underlying implementation, which is different from one OS to the next.
In your specific example, stat is a function defined by standard system headers, but its underlying implementation will vary from system to system. It's possible that the entire function is pulled from msvcrt, but my guess is that msvcrt happens to implement a companion function which deals with all the system-specific stuff.

The difference between a program in C++ developed under Windows and Linux

What's the difference between a program developed in C++ under Windows and Linux?
Why can't a program developed under Windows in C++ be used under Linux?
Windows and Linux use different container formats to hold the executable code (PE vs ELF).
Windows and Linux have completely different APIs (except for trivial programs that only use the CRT and STL)
Windows and Linux have a completely different directory structure
You could write a program that can use either set of APIs (for example, using Qt), and that can handle either directory structure, but you still won't be able to run the same file on both operating systems because of the differing container formats.
This can be solved by using Wine.
Native programs are not compatible because Windows has a completely different set of API's than Linux, for one. As others have mentioned, each platform uses a different executable format as well. Also both platforms have their own set of libraries that programs will be linked against and/or share. For example, a Windows program will typically be developed in Visual Studio using windows-specific libraries such as MFC, Win32 API, etc. These libraries are not available in linux, so the program will not even compile unless care is taken to make sure cross-platform libraries (such as QT) are used.
If you are careful, however, you can use cross-platform libraries in your code and you can get the same program to compile under both platforms. For such a program you would need to carefully put any platform-specific details (file system locations, etc) in their own files. Then, you would need to setup the proper #define statements and/or makefile directives to ensure the proper files are included in the build for each platform.
Of course, if you use a "cross-platform" language such as Java or Python, and do not use any platform-specific code in your implementation, then your program can run under both environments.
Note Although the executable formats are different, some programs developed on Windows can be executed under Linux using an emulator called WINE.
In a nutshell,
Windows runs PE format executables
Linux runs ELF format executables
Furthermore, even if there were a tool to convert between PE and ELF, the program instructions necessary to interface with the operating system are completely different between Windows and Linux. Only the most restricted computation-only code (that only does calculations and doesn't interact with the operating system at all) could be ported between systems without special action. However, this is rarely done.
I believe some versions of Linux allow you to directly load device drivers designed for Windows without recompiling. However, this is an extremely special purpose application and the technique is not generally used.
Each operating system defines an API. If you code to call the Win32 API, it won't be there on Linux. If you code to the POSIX API, it won't jump right out at you in Windows.
To learn more about this, download a significant open source program (for example, Perl or Python) and see how its 'configure' script makes arrangements to compile in either place.
When a C++ program is compiled on a platform, it ultimately changes into a form that machine can understand (i.e. Machine code). Under the hood, the program uses system calls to perform privileged action. These system calls are implemented via methods or APIs. These methods differ from platform to platform. Hence on every platform, the compiled code is different. There are many cross-compilers available if you want to compile your code for a different platform.
Not to be overly pedantic, but developing a program is different than building it and executing it. In many cases, a program written on one operating system can be built and compiled to execute on another. Other programs, as others have pointed out, rely on certain functionality provided only by a particular OS or libraries resident only on that OS. As a result, it must be built and run on that OS.
C++ is itself portable. But some C++ libraries are not. If a C++ program uses some libraries, which are not portable, then this program is not portable.
For example, a C++ program uses MFC to draw the GUI stuff, because MFC is supported only in Windows, so this C++ program cannot be compiled or run on Linux directly.
There are two major reasons.
Theoretically, the same program (source code) for some languages like C, can run on both Windows and Linux. But the compilation only differs; this means you have to compile the same source code file for each platform.
But actually, each operating system has a different set of APIs. And different techniques to get job done faster... Which usually attract developers to use them. And they don't stick to standards, so they lose portability.
This was for native programs... Anyway, there are the Java and Python languages... They are truly cross-platform, but you have to sacrifice speed for sake of portability.
This is a large topic.
First, Windows and Linux aren't binary comparable. This means that even the simplest of programs will not be recognized from one machine to the other. This is why interpreted languages like PHP, Perl, Python and Java are becoming so popular, but even these don't all support the same set of features on each platform.
Library dependence / OS support: Any significantly complicated program will need to access the system is some way, and many of the features available on one system are not available on the other. There are a million examples; just look on so for the Linux equivalent of blank or Windows equivalent of blank. Moving beyond OS support applications are built mostly on top of libraries of functions and some of those are just not available on both systems.

Platform C Preprocessor Definitions

I'm writing a small library in C++ that I need to be able to build on quite a few different platforms, including iPhone, Windows, Linux, Mac and Symbian S60. I've written most of the code so that it is platform-agnostic but there are some portions that must be written on a per-platform basis.
Currently I accomplish this by including a different header depending on the current platform but I'm having trouble fleshing this out because I'm not sure what preprocessor definitions are defined for all platforms. For windows I can generally rely on seeing WIN32 or _WIN32. For Linux I can rely on seeing _UNIX_ but I am less certain about the other platforms or their 64-bit variants. Does anyone have a list of the different definitions found on platforms or will I have to resort to a config file or gcc parameter?
I have this sourceforge pre-compiler page in my bookmarks.
The definitions are going to be purely up to your compiler vendor. If you are using the same compiler (say, gcc) on all your platforms then you will have a little bit easier time of it.
You might also want to try to instead organize your project such that most of the .h files are not platform dependent. Split your implementation (cpp files) into separate files; one for the nonspecific stuff and one for each platform. The platform specific ones can include 'private' headers that only make sense for that platform. You may have to make adapter functions to get something like this to work 100% (when the system libs take slightly differed arguments) but I have found it to be really helpful in the end, and bringing on a new platform is a whole lot easier in the future.
Neither the C nor the C++ standards define such symbols, so you are going to be at the mercy of specific C or C++ implementations. A list of commonly used symbols would be a useful thing to have, but unfortunately I haven't got one.
I don't think there exists a universal list of platform defines judging by the fact that every cross-platform library I have seen has an ad-hoc config.h full of these stuff. But you can consider looking at the ones used by fairly portable libraries like libpng, zlib etc.
Here's the one used by libpng
If you want to look through the default preprocessor symbols for a given system on which you have GCC (e.g. Mac OS X, iOS, Linux), you can get a complete list from the command-line thus:
echo 'main(){}' | cpp -dM
These are often of limited use however, as at the stage of the compilation at which the preprocessor operates, most of the symbols identify the operating system and CPU type of only the system hosting the compiler, rather than the system being targeted (e.g. when cross-compiling for iOS). On Mac OS X and iOS, the right way to determine the compile-time characteristics of the system being targeted is
#include <TargetConditionals.h>
This will pick up TargetConditionals.h from the Platform and SDK currently in use, and then you can determine (e.g.) endianness and some other characteristics from some of the Macros. (Look through TargetConditionals.h to see what kinds of info you can glean.)

Reading file names with C++

Is there a way to read file names from a folder using purely C (or C++)? That means without including windows.h (no FindFirstFile(), etc...).
It doesn't look like fstream has this functionality. I know that file names are operating system dependent, but I was hoping there is some library that will allow it in Windows.
boost filesystem is a nice solution. Of course under the hood, it will still be using the windows API calls (when you build on windows), but this is abstracted away from you.
C++ typically does not supply you with such functionality. A cross-platform solution is to use boost::filesystem.
Try the POSIX functions opendir() and readdir() for iterating through directories. See this link for the manual page with some great example code. These functions should be available on most platforms, both Windows and UNIX.
If you wish to use opendir() and readdir() on windows, you can download MinGW, a windows port of the famous GNU compiler collection. It includes windows ports of the UNIX header files, including dirent.h, which will allow you to use the specified functions. Keep in mind these will call native API's either way.
-John