OS Platform support macros and boost library - c++

I wrote below code to detect OS and it is working fine with boost version > 1.55 but older boost library ( e.g. 1.48 ) do not support operating system macros.
Below is the sample code that works fine with boost >= 1.55.
std::string GetOSPlatform()
{
std::string platformStr = "Unknown";
#if defined(BOOST_OS_MACOS) || defined(BOOST_OS_IOS)
platformStr = "osx";
#endif
#if defined(BOOST_OS_WINDOWS)
platformStr = "windows";
#if BOOST_ARCH_X86_64
platformStr += "-x64";
#endif
#endif
#if defined(BOOST_OS_UNIX) || defined(BOOST_OS_LINUX)
platformStr = "linux";
#if BOOST_ARCH_X86_64
platformStr += "-x64";
#endif
#endif
#if BOOST_OS_SOLARIS
platformStr = "solaris";
#if BOOST_ARCH_SPARC
platformStr += "-sparc";
#else
platformStr += "-x64";
#endif
#endif
#if BOOST_OS_HPUX
platformStr = "hp-ux";
#endif
return platformStr;
}
int main()
{
std::string pltform = GetOSPlatform();
std::cout << "platform....." << pltform << std::endl;
return 0;
}
Here "BOOST_OS_*" macros are not supported with boost version < 1.55 so how to replace above code so that it works with older boost version as well ?
Any suggestions?

In order to get the code to work, you add some conditional compilation based on the version of Boost that you are running. If it's 1.55 or later, you just compile the code as it is. If it's an earlier version, you simply reproduce the OS detection code that later Boost versions use locally, e.g. by simply copying the code from a later version.

Related

C++/C Code to have different execution block on M1 and Intel

I am writing a code for macOS application.
The application would be running on M1 based Macs as well as Intel based Macs also.
What would be the switch to differentiate M1 and Intel?
if (M1)
{
do something for M1
}
else if (Intel)
{
do something for Intel
}
I think, you can use __arm__ to detect arm architecture:
#ifdef __arm__
//do smth on arm (M1)
#else
//do smth on x86 (Intel)
#endif
I was just fooling around with this and found this reference for Objective-C from apple that seemed to work with clang for C++.
// Objective-C example
#include "TargetConditionals.h"
#if TARGET_OS_OSX
// Put CPU-independent macOS code here.
#if TARGET_CPU_ARM64
// Put 64-bit Apple silicon macOS code here.
#elif TARGET_CPU_X86_64
// Put 64-bit Intel macOS code here.
#endif
#elif TARGET_OS_MACCATALYST
// Put Mac Catalyst-specific code here.
#elif TARGET_OS_IOS
// Put iOS-specific code here.
#endif
https://developer.apple.com/documentation/apple-silicon/building-a-universal-macos-binary
I specifically checked to see if TARGET_CPU_ARM64 was defined in my header.
Hopefully this helps someone.
If you need a runtime check instead of compile time check, you can think of using something like below
#include <sys/sysctl.h>
#include <mach/machine.h>
int main(int argc, const char * argv[])
{
cpu_type_t type;
size_t size = sizeof(type);
sysctlbyname("hw.cputype", &type, &size, NULL, 0);
int procTranslated;
size = sizeof(procTranslated);
// Checks whether process is translated by Rosetta
sysctlbyname("sysctl.proc_translated", &procTranslated, &size, NULL, 0);
// Removes CPU_ARCH_ABI64 or CPU_ARCH_ABI64_32 encoded with the Type
cpu_type_t typeWithABIInfoRemoved = type & ~CPU_ARCH_MASK;
if (typeWithABIInfoRemoved == CPU_TYPE_X86)
{
if (procTranslated == 1)
{
cout << "ARM Processor (Running x86 application in Rosetta)";
}
else
{
cout << "Intel Processor";
}
}
else if (typeWithABIInfoRemoved == CPU_TYPE_ARM)
{
cout << "ARM Processor";
}
}

How to port NDIS 6.2 to NDIS 6.3 using NDIS_SUPPORT_NDIS630?

I have NDIS 6.2 Supporting Miniport Driver . Now I want to port NDIS 6.2 to NDIS 6.3 .
https://msdn.microsoft.com/en-us/library/windows/hardware/dn232191(v=vs.85).aspx
Using this link I changed some general requirements and Power Management for Enhancements in NDIS 6.30 .
i put all changes are in same NDIS 6.2 file .
The chnages are (miniport.cpp)
ndisMiniportDriverCharacteristics.MajorNdisVersion = 6;
ndisMiniportDriverCharacteristics.MinorNdisVersion = 30;
ndisMiniportDriverCharacteristics.MajorDriverVersion = VERSION_MAJOR_NUM;
ndisMiniportDriverCharacteristics.MinorDriverVersion = VERSION_MINOR_NUM;
ndisMiniportDriverCharacteristics.SetOptionsHandler = CMiniport::SetOptions;
ndisMiniportDriverCharacteristics.InitializeHandlerEx = CMiniport::InitializeEx;
...... ....etc
then inside InitializeEx() funcion the changes for NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES are :
NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES ndisMiniportAdapterRegistrationAttributes;
NdisZeroMemory(&ndisMiniportAdapterRegistrationAttributes, sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES));
#if (NDIS_SUPPORT_NDIS630)
C_ASSERT(sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES) >= NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_2);
ndisMiniportAdapterRegistrationAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;
ndisMiniportAdapterRegistrationAttributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_2;
ndisMiniportAdapterRegistrationAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_2;
#else
C_ASSERT(sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES) >= NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1);
ndisMiniportAdapterRegistrationAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;
ndisMiniportAdapterRegistrationAttributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
ndisMiniportAdapterRegistrationAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
#endif // NDIS MINIPORT VERSION
ndisMiniportAdapterRegistrationAttributes.MiniportAdapterContext = CMiniport::m_pMiniport;
#if (NDIS_SUPPORT_NDIS630)
ndisMiniportAdapterRegistrationAttributes.AttributeFlags |= NDIS_MINIPORT_ATTRIBUTES_NO_PAUSE_ON_SUSPEND;
#else
ndisMiniportAdapterRegistrationAttributes.AttributeFlags = NDIS_MINIPORT_ATTRIBUTES_SURPRISE_REMOVE_OK | NDIS_MINIPORT_ATTRIBUTES_NDIS_WDM;
#endif
ndisMiniportAdapterRegistrationAttributes.CheckForHangTimeInSeconds = 5;
and for the chnage NDIS_PM_CAPABILITIES i wrote like this :
NDIS_PM_CAPABILITIES ndisPmCapabilities;
NdisZeroMemory(&ndisPmCapabilities, sizeof(NDIS_PM_CAPABILITIES));
#if (NDIS_SUPPORT_NDIS630)
C_ASSERT(sizeof(NDIS_PM_CAPABILITIES) >= NDIS_SIZEOF_NDIS_PM_CAPABILITIES_REVISION_2);
ndisPmCapabilities.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
ndisPmCapabilities.Header.Size = NDIS_SIZEOF_NDIS_PM_CAPABILITIES_REVISION_2;
ndisPmCapabilities.Header.Revision = NDIS_PM_CAPABILITIES_REVISION_2;
ndisPmCapabilities.MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
ndisPmCapabilities.MinPatternWakeUp = NdisDeviceStateUnspecified;
ndisPmCapabilities.MinLinkChangeWakeUp = NdisDeviceStateUnspecified;
#else
C_ASSERT(sizeof(NDIS_PM_CAPABILITIES) >= NDIS_SIZEOF_NDIS_PM_CAPABILITIES_REVISION_1);
ndisPmCapabilities.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
ndisPmCapabilities.Header.Size = NDIS_SIZEOF_NDIS_PM_CAPABILITIES_REVISION_1;
ndisPmCapabilities.Header.Revision = NDIS_PM_CAPABILITIES_REVISION_1;
ndisPmCapabilities.MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
ndisPmCapabilities.MinPatternWakeUp = NdisDeviceStateUnspecified;
ndisPmCapabilities.MinLinkChangeWakeUp = NdisDeviceStateUnspecified;
#endif // NDIS MINIPORT VERSION
So my doubts are :
can i use this NDIS 6.30 for windows 7 NDIS 6.2 ?
how to activate NDIS_SUPPORT_NDIS630 macro ?
in ndis.h WDK file the macros are like this :
#if !defined(NDIS_SUPPORT_NDIS630)
#if (((defined (NDIS_MINIPORT_MAJOR_VERSION) && (NDIS_MINIPORT_MAJOR_VERSION >= 6)) && \
(defined (NDIS_MINIPORT_MINOR_VERSION) && (NDIS_MINIPORT_MINOR_VERSION >= 30))) || \
(defined (NDIS630)) || NDIS_WRAPPER)
#define NDIS_SUPPORT_NDIS630 1
#else
#define NDIS_SUPPORT_NDIS630 0
#endif
#endif // !defined(NDIS_SUPPORT_NDIS630)
but when i use ndisPmCapabilities.Header.Revision = NDIS_PM_CAPABILITIES_REVISION_2; directly i got error like
NDIS_PM_CAPABILITIES_REVISION_2 is not defined .
How to use this NDIS_SUPPORT_NDIS630 macro ?
You activate the relevant NDIS version by defining the appropriate NDIS6XX_MINIPORT in your project. You can see it in more details in comments at the beginning of ndis.h header.
You can compile your driver with whatever NDIS version that you want, but they are not backwards compatible - each Windows version is provided with a different NDIS version, naturally older OS versions can't work with newer NDIS versions.
Windows 7 does not support NDIS 6.30. Windows 7 only goes up to 6.20.

c++ can't get "wcout" to print unicode, and leave "cout" working

can't get "wcout" to print unicode string in multiple code pages, together with leaving "cout" to work
please help me get these 3 lines to work together.
std::wcout<<"abc "<<L'\u240d'<<" defg "<<L'א'<<" hijk"<<std::endl;
std::cout<<"hello world from cout! \n";
std::wcout<<"hello world from wcout! \n";
output:
abc hello world from cout!
i tried:
#include <io.h>
#include <fcntl.h>
_setmode(_fileno(stdout), _O_U8TEXT);
problem:
"wcout" failed
tried:
std::locale mylocale("");
std::wcout.imbue(mylocale);
and:
SetConsoleOutputCP(1251);
and
setlocale(LC_ALL, "");
and
SetConsoleCP(CP_UTF8)
Nothing worked
C++ says:
[C++11: 27.4.1/3]: Mixing operations on corresponding wide- and narrow-character streams follows the same semantics as mixing such operations on FILEs, as specified in Amendment 1 of the ISO C standard.
And the referenced document says:
The definition of a stream was changed to include the concept of an orientation for both text and binary streams. After a stream is associated with a file, but before any operations are performed on the stream, the stream is without orientation. If a wide-character input or output function is applied to a stream without orientation, the stream becomes wide-oriented. Likewise, if a byte input or output operation is applied to a stream with orientation, the stream becomes byte-oriented. Thereafter, only the fwide() or freopen() functions can alter the orientation of a stream.
Byte input/output functions shall not be applied to a wide-oriented stream and wide-character input/output functions shall not be applied to a byte-oriented stream.
By my interpretation this means, in short, do not mix std::cout and std::wcout.
Microsoft requires a bit of non-standard set-up with _setmode() before wcout or wcin can work. This example is pretty heavy on the boilerplate, so not as clear as it could possibly be, but it runs on clang++, g++ and MSVC++:
#include <iostream>
#include <locale>
#include <locale.h>
#include <stdlib.h>
#ifndef MS_STDLIB_BUGS // Allow overriding the autodetection.
/* The Microsoft C and C++ runtime libraries that ship with Visual Studio, as
* of 2017, have a bug that neither stdio, iostreams or wide iostreams can
* handle Unicode input or output. Windows needs some non-standard magic to
* work around that. This includes programs compiled with MinGW and Clang
* for the win32 and win64 targets.
*/
# if ( _MSC_VER || __MINGW32__ || __MSVCRT__ )
/* This code is being compiled either on MS Visual C++, or MinGW, or
* clang++ in compatibility mode for either, or is being linked to the
* msvcrt.dll runtime.
*/
# define MS_STDLIB_BUGS 1
# else
# define MS_STDLIB_BUGS 0
# endif
#endif
#if MS_STDLIB_BUGS
# include <io.h>
# include <fcntl.h>
#endif
#if !HAS_APP17_FILESYSTEM && !HAS_TS_FILESYSTEM && __has_include(<filesystem>)
# include <filesystem> /* MSVC has this header, but not the standard API. */
# if __cpp_lib_filesystem >= 201703
# define HAS_CPP17_FILESYSTEM 1
# endif
#endif
#if !HAS_CPP17_FILESYSTEM && __has_include(<experimental/filesystem>)
# include <experimental/filesystem>
/* Microsoft screws this one up, too, by not defining the feature-test
* macro specified by the standard.
*/
# if __cpp_lib_experimental_filesystem >= 201406 || MS_STDLIB_BUGS
# define HAS_TS_FILESYSTEM 1
/* With g++6, this requires -lstdc++fs, AFTER this source file on the
* command line.
*/
# endif
#endif
#if HAS_CPP17_FILESYSTEM
using std::filesystem::absolute;
using std::filesystem::current_path;
using std::filesystem::directory_entry;
using std::filesystem::directory_iterator;
using std::filesystem::is_directory;
using std::filesystem::exists;
using std::filesystem::path;
#elif HAS_TS_FILESYSTEM
using std::experimental::filesystem::absolute;
using std::experimental::filesystem::current_path;
using std::experimental::filesystem::directory_entry;
using std::experimental::filesystem::directory_iterator;
using std::experimental::filesystem::is_directory;
using std::experimental::filesystem::exists;
using std::experimental::filesystem::path;
#else
# error "This library has neither <filesystem> nor <experimental/filesystem>."
#endif
void init_locale(void)
// Does magic so that wcout can work.
{
#if MS_STDLIB_BUGS
// Windows needs a little non-standard magic.
constexpr char cp_utf16le[] = ".1200"; // UTF-16 little-endian locale.
setlocale( LC_ALL, cp_utf16le );
_setmode( _fileno(stdout), _O_WTEXT );
/* Repeat for _fileno(stdin), if needed. */
#else
// The correct locale name may vary by OS, e.g., "en_US.utf8".
constexpr char locale_name[] = "";
setlocale( LC_ALL, locale_name );
std::locale::global(std::locale(locale_name));
std::wcin.imbue(std::locale())
std::wcout.imbue(std::locale());
#endif
}
using std::endl;
int main( const int argc, const char * const argv[] )
{
init_locale();
const path cwd = (argc > 1) ? absolute(path( argv[1], std::locale() ))
: absolute(current_path());
if (exists(cwd)) {
std::wcout << cwd.wstring() << endl;
} else {
std::wcerr << "Path does not exist.\n";
return EXIT_FAILURE;
}
if (is_directory(cwd)) {
for ( const directory_entry &f : directory_iterator(cwd) )
std::wcout << f.path().filename().wstring() << endl;
}
return EXIT_SUCCESS;
}
That’s probably a lot more complicated than it really needed to be: std::filesystem is unsupported as of 2018, but <experimental/filesystem> is never going to be removed.
Here’s a simplified version that includes only the boilerplate to get wcout to work:
#include <iostream>
#include <locale>
#include <locale.h>
#ifndef MS_STDLIB_BUGS
# if ( _MSC_VER || __MINGW32__ || __MSVCRT__ )
# define MS_STDLIB_BUGS 1
# else
# define MS_STDLIB_BUGS 0
# endif
#endif
#if MS_STDLIB_BUGS
# include <io.h>
# include <fcntl.h>
#endif
void init_locale(void)
{
#if MS_STDLIB_BUGS
constexpr char cp_utf16le[] = ".1200";
setlocale( LC_ALL, cp_utf16le );
_setmode( _fileno(stdout), _O_WTEXT );
#else
// The correct locale name may vary by OS, e.g., "en_US.utf8".
constexpr char locale_name[] = "";
setlocale( LC_ALL, locale_name );
std::locale::global(std::locale(locale_name));
std::wcin.imbue(std::locale())
std::wcout.imbue(std::locale());
#endif
}
It's because Unicode is not representable in the codepage causing wcout to fail.
std::wcout<<"abc "<<L'\u240d'<<" defg "<<L'א'<<" hijk"<<std::endl;
if(std::wcout.fail()){
std::cout<<"\nConversion didn't succeed\n";
std::wcout << "This statement has no effect on the console";
std::wcout.clear();
std::wcout<<"hello world from wcout! \n";
}
std::cout<<"hello world from cout! \n";
std::wcout<<"hello world from wcout again! \n";

How do I find the name of an operating system?

The questions pretty simple. I want want a function (C++) or method which will, on call, returun something like
"Windows" //or
"Unix"
Nothing fancy, I dont need the version numbe or anything. Just the os name. A quick google searc didnt turn up anything useful, so I thought I'd post this here
Since you can not have a single binary file which runs over all operating systems, and you need to re-compile your code again. It's OK to use MACROs.
Use macros such as
_WIN32
_WIN64
__unix
__unix__
__APPLE__
__MACH__
__linux__
__FreeBSD__
like this
std::string getOsName()
{
#ifdef _WIN32
return "Windows 32-bit";
#elif _WIN64
return "Windows 64-bit";
#elif __APPLE__ || __MACH__
return "Mac OSX";
#elif __linux__
return "Linux";
#elif __FreeBSD__
return "FreeBSD";
#elif __unix || __unix__
return "Unix";
#else
return "Other";
#endif
}
You should read compiler's manuals and see what MACROS they provided to detect the OS on compile time.
From the Poco source code:
Win32:
std::string EnvironmentImpl::osNameImpl()
{
OSVERSIONINFO vi;
vi.dwOSVersionInfoSize = sizeof(vi);
if (GetVersionEx(&vi) == 0) throw SystemException("Cannot get OS version information");
switch (vi.dwPlatformId)
{
case VER_PLATFORM_WIN32s:
return "Windows 3.x";
case VER_PLATFORM_WIN32_WINDOWS:
return vi.dwMinorVersion == 0 ? "Windows 95" : "Windows 98";
case VER_PLATFORM_WIN32_NT:
return "Windows NT";
default:
return "Unknown";
}
}
Unix:
std::string EnvironmentImpl::osNameImpl()
{
struct utsname uts;
uname(&uts);
return uts.sysname;
}

fatal error: strtok_r.h: No such file or directory (while compiling tesseract-ocr-3.01 in MinGW)

I'm compiling tesseract-ocr-3.01 in MinGW, and I'm getting this error ambigs.cpp:31:22: fatal error: strtok_r.h: No such file or directory
This is the code where the error is:
#ifdef WIN32
#ifndef __GNUC__
#define strtok_r strtok_s
#else
#include "strtok_r.h"
#endif /* __GNUC__ */
#endif /* WIN32 */
Edit
I found this feature request to add strtok_r.h to MinGW. From the comments there:
strtok_r() is an optional POSIX function, required only for
implementations which support POSIX threads. MinGW does not support
POSIX threads; therefore, I don't think that this function has any
place in a base MinGW distribution.
POSIX threads support for MS-Windows is provided by the pthreads-win32
project. Maybe they already provide a strtok_r() implementation. If
so, then you could use it; if not, you might ask them to consider
adding it.
The problem is most easily solved by adding an strtok_r implementation to the project's sources:
char *strtok_r(char *str, const char *delim, char **save)
{
char *res, *last;
if( !save )
return strtok(str, delim);
if( !str && !(str = *save) )
return NULL;
last = str + strlen(str);
if( (*save = res = strtok(str, delim)) )
{
*save += strlen(res);
if( *save < last )
(*save)++;
else
*save = NULL;
}
return res;
}