Is there a way to do #define, #ifdef and the other powerful macros in Swift?
Swift doesn't have a preprocessor and can't use C macros. There are some alternatives though.
For constants you can just use a let statement. For example:
let defaultHeight = 100
There is also some support for build configurations. They have this format.
#if build configuration && !build configuration
statements
#elseif build configuration
statements
#else
statements
#endif
You can replace "build configuration" with the functions os() and arch() that return true or false. os() can take OSX or iOS as arguments while arch() can take x86_64, arm, arm64 and i386 as arguments.
You can see more about how Swift replaces C macros here
Simple Macros
Where you typically used the #define directive to define a primitive constant in C and Objective-C, in Swift you use a global constant instead. For example, the constant definition #define FADE_ANIMATION_DURATION 0.35 can be better expressed in Swift with let FADE_ANIMATION_DURATION = 0.35. Because simple constant-like macros map directly to Swift global variables, the compiler automatically imports simple macros defined in C and Objective-C source files
reference: Page 40, Simple Macros
https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/BuildingCocoaApps.pdf
Related
I was working on a C/C++ project for an embedded system that uses gcc-arm-none-eabi-8-2019-q3-update as a compiler.
I added the use of the strptime function of time.h but initially it was undefined and I found in the compiler inclusions:
#if __XSI_VISIBLE
...strptime...
#endif
So, I solved the problem with:
#undef __XSI_VISIBLE
#define __XSI_VISIBLE 1
#include <time.h>
#undef __XSI_VISIBLE
#define __XSI_VISIBLE 0
Now it works BUT:
What have I done?
What is __XSI_VISIBLE?
What is it for?
Why does this compiler keep it by default at 0?
From https://pubs.opengroup.org/onlinepubs/9699919799/:
The X/Open System Interfaces (XSI) option is the core application programming interface for C and sh programming for systems conforming to the Single UNIX Specification. This is a superset of the mandatory requirements for conformance to POSIX.1-2017.
The __XSI_VISIBLE macro makes visible extensions to "vanilla" POSIX interfaces, which otherwise would be forbidden to be in the name space. Remember that C language standards like ISO C and POSIX permit the application to define all non-standard identifiers (in ISO C and "vanilla" POSIX, strptime is not reserved, you can write a function with that name and have it not interfere). By defining so-called feature test macros you extend the set of standard identifiers and reduce those available to define by the application programmer.
Your compiler keeps it at 0 because the implementation vendor chose that it is the application programmer's job to enable XSI when s/he wants it. Application programmers do this by defining the desired feature test macros before header inclusion, e.g. with
#define _POSIX_SOURCE
#define __XSI_VISIBLE 1
#include <time.h>
or pass -D__XSI_VISIBLE=1 to the compiler.
The correct defs to use are -D_XOPEN_SOURCE=1 and -D_GNU_SOURCE=1. These are used to conditionally define __XSI_VISIBLE and __GNU_VISIBLE respectively in <sys/features.h>. Defining __XSI_VISIBLE and __GNU_VISIBLE will not always work because they are overridden in <sys/features.h>.
I'm using CodeBlocks and GCC compiler. I'd like to use "string safe functions" e.g strlen_s, strcpy_s, but compiler shows an error:
Undefined reference to strlen_s.
I then add a line to the code:
#define __STDC_WANT_LIB_EXT1__ 1
As well as writing the following in the Compiler Options (settings -> compiler -> global compiler settings -> other compiler options):
-std=c11
In the book that I'm reading there's a code to checking whether my compiler supports these functions. The code is as follows:
#include <stdio.h>
int main()
{
#if defined __STDC_WANT_LIB_EXT1__
printf("optional functions are defined");
#else
printf("optional functions are not defined");
#endif
return 0;
}
When I run this code I see "optional functions are defined". I've also reinstalled CodeBlocks but I still get these errors.
Should I install another compiler? If I should, which one will be the best?
#define __STDC_WANT_LIB_EXT1__ 1 is expected to be defined by your application - you have to define it yourself to enable the use of the bounds-checking interface functions.
In order to see if the bounds-checking interface is at all available, you need to check if __STDC_LIB_EXT1__ is defined by the compiler.
Note that no function called strlen_s exists.
This test is not sufficient, you should also test whether the implementation defines the macro __STDC_LIB_EXT1__.
These functions are from a part of the C standard that is called "Annex K" and that is optional. With this macro you test if your C library provides that feature, with the WANT macro defined before any includes you tell the compiler that you want to use these features from Annex K.
Annex K is much controversial, and not many public domain C libraries implement it. Many people think that its interfaces don't provide the security that it claims.
And for the book that you are reading this doesn't seem to be too reliable. But then, I may be biased on that point.
Is there any Ruby equivalent of C/C++ macro?
#define something somethingelse
Ruby projects typically have neither a pre-processing nor a compilation step and usage of any pre-processor is not common.
You can define constants by using capitalized variable names.
However, if you really need a pre-processor then you can use CPP with ruby or any other language - it does not really care about the actual syntax.
There isn't a direct equivalent, but you can do it. For example,
#DEFINE PI 3.14159
in the C/C++ Preprocessor can be
PI=3.14159
in ruby. Capitalized variables are constants in ruby.
The other type of macro being, for example
#DEFINE ADD(A, B) A + B
is
def add(a, b)
a + b
end
in ruby. There is real reason to use a C/C++ style macro in ruby when it comes to function macros as you can easily define methods in ruby that work just as well as C/C++ style macros.
I'm working with some code that is supposed to support both C++11 and C++03. I would like to mark a function [[noreturn]] but since that does not exist in C++03 I'm trying to figure out how best to guard it with preprocessor symbols.
In this email thread, it's suggested to try to check whether an individual feature is supported rather than all of C++11:
https://cmake.org/pipermail/cmake/2013-February/053635.html
Todd Greer writes:
You might consider using code from Boost's config subsystem. There's a list of dozens of macros they define to set what features are available in what compilers here: http://www.boost.org/doc/libs/1_53_0/libs/config/doc/html/boost_config/boost_macro_reference.html#boost_config.boost_macro_reference.macros_that_describe_c__11_features_not_supported
--
Todd Greer
Principal Scientist, Affinegy, Inc.
However, I didn't find anything that seems to do what I want. (In the boost config stuff, or elsewhere.)
Does anyone know a way to do this directly with a C preprocessor trick, or know of an existing CMake module that detects this feature? (If not I guess I will try to kludge one together.)
Try something like this:
#ifdef __has_cpp_attribute
# if __has_cpp_attribute(noreturn)
# define NO_RETURN [[noreturn]]
# else
# define NO_RETURN
# endif
#else
# define NO_RETURN
#endif
NO_RETURN void myFunc()
{
//...
}
You can perform the following CMake check:
include(CheckCXXSourceCompiles)
check_cxx_source_compiles("
[[noreturn]] void testFunc()
{}
int main(void)
{
return 0;
}
" HAS_ATTRIBUTE_NORETURN
)
Then you can pass HAS_ATTRIBUTE_NORETURN to your config.h and use this in your C++ code with an ifdef.
The advantage is, that you don't miss compilers that do not set the right _cpluplus variable or does not support the __has_attribute feature.
Depending on your setting, you might need to add flags to set the C++ mode (like -std=c++11 or c++0x). This can be done with CMakePushCheckState and modifying CMAKE_REQUIRED_FLAGS.
I want to use my school custom library in a C++ project but the library linking seems not working... When I create my program in C and I try to compile it, it work...
See by yourself:
I think that the X11 and/or Xext libraries dependencies of the Mlx are in cause, there can be some
#if __cplusplus
void *x11_mlx_function_wanted(void);
#endif
I had already check if the mlx contains some check like that and I saw nothing.
Thank you in advance
EDIT
And I succeed in objective-c.
The problem is C++ name-mangling. If you declare a function in C11, it ends up with a "mangled" name, which encodes the namespace and the types of the arguments. That's necessary because in C++, various overloads can exist for the same function name. The overloads are independent functions; they do not even have to be in the same object library.
In the object library itself, the functions will have ordinary C names. But since the header file is processed with a C++ compiler, the declared functions will be named as though they were C++ functions.
One possible solution might be to declare all the included functions to be C functions:
extern "C" {
#include "/usr/X11/include/mlx.h"
}