How can I compose translation units in C? [duplicate] - c++

I was wondering if it's possible to use C constructors in VC just as it is possible to use them in GCC.
The gcc way is quite straight using the __attribute__ keyword, unfortunately VC doesn't seem to even know this keyword, as I'm not a Win32 programmer I wonder if there's some sort of equivalent keyword for such things.
Just to note - this is a C program, not a C++ or C# even, (as 'twas quite easy to do that in those languages)

Below C code demonstrates how to define a void(void) function to be called at program/library load time, before main executes.
For MSVC, this places a pointer to the function in the user initializer section (.CRT$XCU), basically the same thing the compiler does for the constructor calls for static C++ objects. For GCC, uses a constructor attribute.
// Initializer/finalizer sample for MSVC and GCC/Clang.
// 2010-2016 Joe Lowe. Released into the public domain.
#include <stdio.h>
#include <stdlib.h>
#ifdef __cplusplus
#define INITIALIZER(f) \
static void f(void); \
struct f##_t_ { f##_t_(void) { f(); } }; static f##_t_ f##_; \
static void f(void)
#elif defined(_MSC_VER)
#pragma section(".CRT$XCU",read)
#define INITIALIZER2_(f,p) \
static void f(void); \
__declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \
__pragma(comment(linker,"/include:" p #f "_")) \
static void f(void)
#ifdef _WIN64
#define INITIALIZER(f) INITIALIZER2_(f,"")
#else
#define INITIALIZER(f) INITIALIZER2_(f,"_")
#endif
#else
#define INITIALIZER(f) \
static void f(void) __attribute__((constructor)); \
static void f(void)
#endif
static void finalize(void)
{
printf( "finalize\n");
}
INITIALIZER( initialize)
{
printf( "initialize\n");
atexit( finalize);
}
int main( int argc, char** argv)
{
printf( "main\n");
return 0;
}

You are probably interested in DllMain.

I don't think there's a way to avoid using C++ features with MSVC. (MSVC's C support sucks anyways.)
Untested, but this should at least allow the same code to work in both MSVC and GCC.
#if defined(_MSC_VER)
struct construct { construct(void (*f)(void)) { f(); } };
#define constructor(fn) \
void fn(void); static constructor constructor_##fn(fn)
#elif defined(__GNUC__)
#define constructor(fn)
void fn(void) __attribute__((constructor))
#endif
static constructor(foo);
void foo() {
...
}

I tried the last answer in MSVC like
#ifdef _MSC_VER
#pragma section(".CRT$XCU",read)
#define INITIALIZER2_(f,p) \
static void f(void); \
__declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \
__pragma(comment(linker,"/include:" p #f "_")) \
static void f(void)
#ifdef _WIN64
#define INITIALIZER(f) INITIALIZER2_(f,"")
#else
#define INITIALIZER(f) INITIALIZER2_(f,"_")
#endif
#else
#define INITIALIZER(f) \
static void f(void) __attribute__((constructor)); \
static void f(void)
#endif
but INITIALIZER(f) can't appear in 2 different files with the same function name passed to INITIALIZER, the following definition will allow that
#ifdef _MSC_VER
#define INITIALIZER(f) \
static void f();\
static int __f1(){f();return 0;}\
__pragma(data_seg(".CRT$XIU"))\
static int(*__f2) () = __f1;\
__pragma(data_seg())\
static void f()
#else
#define INITIALIZER(f) \
__attribute__((constructor)) static void f()
#endif

Related

Issue with nested #define for defining a function with variadic arguments

How can I define a nested #define into a macro with variadic arguments
#ifndef MY_PRINTF
#define MY_PRINTF(f_, ...) { \
#ifdef USE_WRITE_DEBUG_INFO \
char buff[200]; \
sprintf(buff, (f_), __VA_ARGS__); \
WriteDebugInfo(buff); \
#else \
printf((f_), __VA_ARGS__); \
#endif \
}
#endif
Visual studio complains about missing directives. I'd appreciate for any hint.
You can't use preprocessor directives while defining a #define. This means that your #ifdef USE_WRITE_DEBUG_INFO won't work.
For this case, use a function rather than a macro:
#include <cstdarg>
void my_printf(const char* format, ...) {
#ifdef USE_WRITE_DEBUG_INFO
char buff[200];
va_list args;
va_start(args, format);
// Note: uses the snprintf variant rather than sprintf variant,
// avoiding buffer overlows.
vsnprintf(buff, 200, format, args);
va_end(args);
WriteDebugInfo(buff);
#else
va_list args;
va_start(args, format);
vprintf(format, args);
va_end(args);
#endif
}
In general, you'd have to bring the preprocessor directives outside of the #define:
#ifndef MY_PRINTF
#ifdef USE_WRITE_DEBUG_INFO
// do { ... } while (false) makes the macro behave mostly like a regular function call.
#define MY_PRINTF(f_, ...) do { \
char buff[200]; \
sprintf(buff, (f_), __VA_ARGS__); \
WriteDebugInfo(buff); \
} while (false)
#else
#define MY_PRINTF(f_, ...) printf((f_), __VA_ARGS__)
#endif
#endif

MSVC equivalent for: void __attribute__((constructor)) [duplicate]

I was wondering if it's possible to use C constructors in VC just as it is possible to use them in GCC.
The gcc way is quite straight using the __attribute__ keyword, unfortunately VC doesn't seem to even know this keyword, as I'm not a Win32 programmer I wonder if there's some sort of equivalent keyword for such things.
Just to note - this is a C program, not a C++ or C# even, (as 'twas quite easy to do that in those languages)
Below C code demonstrates how to define a void(void) function to be called at program/library load time, before main executes.
For MSVC, this places a pointer to the function in the user initializer section (.CRT$XCU), basically the same thing the compiler does for the constructor calls for static C++ objects. For GCC, uses a constructor attribute.
// Initializer/finalizer sample for MSVC and GCC/Clang.
// 2010-2016 Joe Lowe. Released into the public domain.
#include <stdio.h>
#include <stdlib.h>
#ifdef __cplusplus
#define INITIALIZER(f) \
static void f(void); \
struct f##_t_ { f##_t_(void) { f(); } }; static f##_t_ f##_; \
static void f(void)
#elif defined(_MSC_VER)
#pragma section(".CRT$XCU",read)
#define INITIALIZER2_(f,p) \
static void f(void); \
__declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \
__pragma(comment(linker,"/include:" p #f "_")) \
static void f(void)
#ifdef _WIN64
#define INITIALIZER(f) INITIALIZER2_(f,"")
#else
#define INITIALIZER(f) INITIALIZER2_(f,"_")
#endif
#else
#define INITIALIZER(f) \
static void f(void) __attribute__((constructor)); \
static void f(void)
#endif
static void finalize(void)
{
printf( "finalize\n");
}
INITIALIZER( initialize)
{
printf( "initialize\n");
atexit( finalize);
}
int main( int argc, char** argv)
{
printf( "main\n");
return 0;
}
You are probably interested in DllMain.
I don't think there's a way to avoid using C++ features with MSVC. (MSVC's C support sucks anyways.)
Untested, but this should at least allow the same code to work in both MSVC and GCC.
#if defined(_MSC_VER)
struct construct { construct(void (*f)(void)) { f(); } };
#define constructor(fn) \
void fn(void); static constructor constructor_##fn(fn)
#elif defined(__GNUC__)
#define constructor(fn)
void fn(void) __attribute__((constructor))
#endif
static constructor(foo);
void foo() {
...
}
I tried the last answer in MSVC like
#ifdef _MSC_VER
#pragma section(".CRT$XCU",read)
#define INITIALIZER2_(f,p) \
static void f(void); \
__declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \
__pragma(comment(linker,"/include:" p #f "_")) \
static void f(void)
#ifdef _WIN64
#define INITIALIZER(f) INITIALIZER2_(f,"")
#else
#define INITIALIZER(f) INITIALIZER2_(f,"_")
#endif
#else
#define INITIALIZER(f) \
static void f(void) __attribute__((constructor)); \
static void f(void)
#endif
but INITIALIZER(f) can't appear in 2 different files with the same function name passed to INITIALIZER, the following definition will allow that
#ifdef _MSC_VER
#define INITIALIZER(f) \
static void f();\
static int __f1(){f();return 0;}\
__pragma(data_seg(".CRT$XIU"))\
static int(*__f2) () = __f1;\
__pragma(data_seg())\
static void f()
#else
#define INITIALIZER(f) \
__attribute__((constructor)) static void f()
#endif

extern keyword in C on more functions

I would like to include one header file in both C and C++, and I have a function defined in C code and few functions defined in external library.
#if defined(__cplusplus)
extern "C" {
#endif
void func0();
#if !defined(__cplusplus)
extern {
#endif
void func1();
int func2(int);
} /* extern */
This code produces compilation error when compiled from C source file
error C2059: syntax error : '{'
Is it possible to fix syntax error directly or I have to use some macros?
EXTERNCPP void func0();
EXTERNC void func1();
EXTERNC int func2(int);
Edit 1:
I do not ask about
Effects of the extern keyword on C functions, I just ask if it is possible to fix syntax in easy way. If it is not possible, i could still remove it completely for C part
Edit 2:
To clarify what I want to get. If header is included
from C++:
extern "C" void func0();
extern "C" void func1();
extern "C" int func2(int);
from C:
void func0();
extern void func1();
extern int func2(int);
extern { is not needed.You need to remove it:-
#if defined(__cplusplus)
extern "C" {
#endif
void func0();
#if !defined(__cplusplus)
#endif
void func1();
int func2(int);
#if defined(__cplusplus)
}
#endif
You can simply omit the extern { line when compiling as a C header.
#if defined(__cplusplus)
extern "C" {
void func0();
#endif
#if !defined(__cplusplus)
void func1();
int func2(int);
#endif
#if defined(__cplusplus)
}
#endif
* [EDIT] answering your last edit:
void func0(); /* included in both versions */
#if defined(__cplusplus)
extern "C" {
void func1();
int func2(int);
#endif
#if !defined(__cplusplus)
extern void func1();
extern int func2(int);
#endif
#if defined(__cplusplus)
}
#endif
If you want to use func0 as extern in C:
#if defined(__cplusplus)
extern "C" {
void func0();
void func1();
int func2(int);
#endif
/* C block */
#if !defined(__cplusplus)
extern void func0();
extern void func1();
extern int func2(int);
#endif
#if defined(__cplusplus)
}
#endif
If you don't want to use it at all (from C) remove it from the C block

ANSI C code for both Objective-C and C++ code?

In my project there are 3 possible types of files: pure C/Objective-C, pure C++ or Objective-C++ code.
How to divide functions in .h file with #define directives into parts to make this file available for all these files? I don't want to rename all the .m files to .mm because of problems with refactoring.
I know that I can write .h file in C which uses C++ .cpp file using the following code:
#ifndef Chadstone_CCCWrapper_h
#define Chadstone_CCCWrapper_h
#ifdef __cplusplus
#include <string.h>
extern "C"
{
#endif
void minMaxCoordinates(char *c, float *minX, float *minY, float *maxX, float *maxY);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif
but what if I want to add functions with using of NSString or list<...>.
You can find it in standard pch-file genarated by Xcode:
#ifdef __OBJC__
#endif
Also you need use CF_EXPORT macro when declaring function to prevent linkage errors.
Example:
#ifndef SOME_H_FILE
#define SOME_H_FILE
#ifdef __OBJC__
#interface SomeObjClass: NSObject
#end
CF_EXPORT void SomeFunctionWithNSString(NSString* str);
#endif
#ifdef __cplusplus
class SomeCPlusPlustClass
{
};
CF_EXPORT void someFunctionWithList(const list<int>& intList);
#ifdef __OBJ__
CF_EXPORT void someComplicatedFunction(NSString* str, const list<int>& intList);
#endif
#endif
CF_EXPORT void someFunction();
typedef struct _SomeStruct
{
} SomeStruct;
#endif

GCC (ARM) equivalent to __declspec(dllexport)

When building application for x86, the following code works fine:
#if defined _WIN32
#define LIB_PRE __declspec(dllexport)
#elif defined __unix__
#define LIB_PRE
#else
#define LIB_PRE __declspec(dllexport)
#endif
But gives an error for GCC (ARM). I have found out that __declspec(dllexport) wont work on GCC. If so, what should I use for GCC (ARM)?
Edit:
Its used in many classes. e.g:
class CJsonValueString : public CJsonValue
{
private:
jstring value;
public:
LIB_PRE CJsonValueString(jstring value);
LIB_PRE CJsonValueString(const CJsonValueString * value);
LIB_PRE jstring ToString() const;
LIB_PRE int ToInt() const;
LIB_PRE int64 ToInt64 () const;
LIB_PRE float ToFloat () const;
LIB_PRE void GetValue(jstring & str) const;
};
Basically, you probably don't need anything special. But if you want (and if working on shared objects, i.e. *.so files), learn more about visibility pragmas and visibility function attributes
And the question is more target operating system specific than target machine specific. (I would imagine that an ARM running some obscure Windows8/ARM system would also need your __declspec; conversely, your __declspec has no sense on Linux/x86).
Here's a simplified version of what we use in our code.
#ifdef __cplusplus
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif
#if defined(__NT__) // MS Windows
#define idaapi __stdcall
#define ida_export idaapi
#if defined(__IDP__) // modules
#define idaman EXTERNC
#else // kernel
#if defined(__X64__) || defined(__NOEXPORT__)
#define idaman EXTERNC
#else
#define idaman EXTERNC __declspec(dllexport)
#endif
#endif
#define ida_local
#elif defined(__UNIX__) // for unix
#define idaapi
#if defined(__MAC__)
#define idaman EXTERNC __attribute__((visibility("default")))
#define ida_local __attribute__((visibility("hidden")))
#else // Linux
#if __GNUC__ >= 4
#define idaman EXTERNC __attribute__ ((visibility("default")))
#define ida_local __attribute__((visibility("hidden")))
#else
#define idaman EXTERNC
#define ida_local
#endif
#endif
#endif
On Linux/OS X, we compile all code by default with -fvisibility=hidden -fvisibility-inlines-hidden and mark up stuff we want to export with idaman, e.g.
idaman bool ida_export set_enum_width(enum_t id, int width);
Since you're exporting C++ methods, you'll probably want to skip the extern "C" part.