C++ Portability Between Windows and Linux

C++ Portability between Windows and Linux

you will have to recompile all libraries for different operating systems. The binary formats for libraries vary from operating system to operating system. More importantly, even if you aren't using libraries, you need to recompile for the simple reason that the different operating systems have different syscall conventions. The only way to get around this is with a virtualizer.

In particular, CygWin cannot run linux programs. at all. CygWin provides only a posix compatibility layer between your program and the Windows kernel.

The situation is a bit less bleak on linux. Wine can run some native windows code (without the need to recompile anything, including your original code). But Wine also has limitations. It is not a complete Windows API, and anything that the library code requires to run must be available on Wine, or else it won't work either. For many, simple apps, this isn't a major problem, but many newer Windows API's, some dark corners of older ones that don't see much use, and in particular, anything that is hardware specific, probably won't be available.

If you intend to run on multiple platforms, it is urgent that you first verify that the libraries you intend to use are also cross platform, or that there are reasonable equivalents for all of the operating systems you wish to use.

portable code between windows and linux

You're looking for:

#if defined(_WIN32)
// Your Windows specific code here
#endif

Edit based on comment:

There is a good discussion of _WIN32 vs WIN32 here: Whats the difference between the win32 defines

How does porting between Linux and Windows work?

this is the point of a cross-platform toolkit like qt or gtk, they provide a platform-agnostic API, which delegates to whichever platform the program is compiled for.

some companies don't use such a toolkit, and write their own (for whatever reason - could well be optimisation-related), meaning they can't just recompile their code for another os.

Are Linux programs as portable as Windows programs?

In the Linux world, binary compatibility is not considered to be as important as source compatibility, since the majority of the ecosystem around Linux is open source. Even when binary compatibility breaks, you can still run old programs after compiling them again. In the Windows ecosystem, this is not possible: most software is closed-source, so an user would depend on the software vendor to update the software for a new OS version. Since this basically never happens, Windows places a lot of emphasis on maintaining binary-level backcompat, to the point that 20 year old binaries can often still run.

Linux has a specification called the Linux Standard Base (LSB) that tries to provide a stable Application Programming Interface (API) for source compatibility and a more limited Application Binary Interface (ABI) for binary compatibility. It is based on POSIX and the Single Unix Specification. However, most Linux distros don't completely implement the LSB. The Red Hat-related group of distros seem to follow it more closely than the Debian- and Ubuntu-related distros.

So unfortunately, the Linux ecosystem does not feature hard guarantees regarding binary compatibility between different distributions or between different versions. In practice though, there's a reasonable amount of compatibility going on. In particular, individual distributions might provide stronger compatibility guarantees. And binaries compiled on one installation of a specific distro version can be used on any installation of that version, provided they have the same architecture – most package managers on Linux use packages with such precompiled binaries. But note that these packages are generally compiled on reference installations with tightly controlled dependencies.

In some cases, the boundaries of architecture, executable format, and OS ABI can be crossed. E.g. the WINE interface layer has an implementation of Windows' “Portable Executable” format, and reimplements significant parts of the Windows ABI, leading to limited Windows→Linux binary compatibility. Architecture boundaries can only be crossed by using emulators (e.g. you can't use software compiled for SPARC on an AMD64 system, even when using the same OS version).

The compatibility for x86 binaries on AMD64 architectures is a special case. The AMD64 instruction set was specifically engineered to be backwards-compatible to x64 (which is why it's so successful). Operating systems still need to provide special kernel-level support for running x86 binaries (which feature 32-bit pointers) on an AMD64 system (which is 64-bit), but all serious operating systems do provide that support.

Portability and length of std::string on Windows vs. Linux

std::string provides public types, like std::string::size_type, that you can use to define your function. You can define your determineFirstPosition function like

inline std::string::size_type determineFirstPosition(const std::string s)
{
for (std::string::size_type i = 0; i < s.length(); ++i)
{
switch (s.at(i))
{
case ' ':
{
break;
}
default:
{
return i;
}
}
}

return s.length();
}

and if you don't want to repeat std::string::size_type all over the place you can add a using declaration to your class to shorten the name like

using pos_type = std::string::size_type;

and then you would just use pos_type.

C program cross platform differences on Windows and Unix OS

That kind of problems usually appear when you don't stick to the bare C standard, and make assumptions about the environment that may not be true. These may include reliance on:

  • nonstandard, platform specific includes (<conio.h>, <windows.h>, <unistd.h>, ...);
  • undefined behavior (fflush(stdin), as someone else reported, is not required to do anything by the standard - it's actually undefined behavior to invoke fflush on anything but output streams; in general, older compilers were more lenient about violation of some subtle rules such as strict aliasing, so be careful with "clever" pointer tricks);
  • data type size (the short=16 bit, int=long=32 bit assumption doesn't hold everywhere - 64 bit Linux, for example, has 64 bit long);
  • in particular, pointer size (void * isn't always 32 bit, and can't be always casted safely to an unsigned long); in general you should be careful with conversions and comparisons that involve pointers, and you should always use the provided types for that kind of tasks instead of "normal" ints (see in particular size_t, ptrdiff_t, uintptr_t)
  • data type "inner format" (the standard does not say that floats and doubles are in IEEE 754, although I've never seen platforms doing it differently);
  • nonstandard functions (__beginthread, MS safe strings functions; on the other side, POSIX/GNU extensions)
  • compiler extensions (__inline, __declspec, #pragmas, ...) and in general anything that begins with double underscore (or even with a single underscore, in old, nonstandard implementations);
  • console escape codes (this usually is a problem when you try to run Unix code on Windows);
  • carriage return format: in normal strings it's \n everywhere, but when written on file it's \n on *NIX, \r\n on Windows, \r on pre-OSX Macs; the conversion is handled automagically by the file streams, so be careful to open files in binary when you actually want to write binary data, and leave them in text mode when you want to write text.

Anyhow an example of program that do not compile on *NIX would be helpful, we could give you preciser suggestions.

The details on the program am yet to get. The students were from our previous batch. Have asked for it. turbo C is what is being used currently.

As said in the comment, please drop Turbo C and (if you use it) Turbo C++, nowadays they are both pieces of history and have many incompatibilities with the current C and C++ standards (and if I remember well they both generate 16-bit executables, that won't even run on 64 bit OSes on x86_64).

There are a lot of free, working and standard-compliant alternatives (VC++ Express, MinGW, Pelles C, CygWin on Windows, and gcc/g++ is the de-facto standard on Linux, rivaled by clang), you just have to pick one.



Related Topics



Leave a reply



Submit