I am trying to get started using mingw (MinGW-w64) and eclipse after working in C++Builder for a long time. I'm very confused.
My work mostly revolves around a vendor supplied API which is MSVC-centric. It consists of 3 header files and a couple of libs. I was able to use their headers unchanged in C++Builder but am running into lots of problems with g++.
#define GX_WRAPPER_FUNC __declspec(dllexport)
#define GX_STANDARD_FUNC
#define GX_WRAPPER_CALL _cdecl
#define GX_STANDARD_CALL _stdcall
#define GX_OBJECT_PTR void*
#define GX_VAR
#define GX_CONST const
#define GX_VOID void
#define GX_LONG long
#define GX_DOUBLE double
#define GX_HANDLE long
#define GX_LONG_PTR long*
#define GX_DOUBLE_PTR double*
#define GX_HANDLE_PTR long*
#define GX_ASTR_PTR char*
#define GX_WSTR_PTR wchar_t*
#if defined(GEO_UTF8)
#define GX_STR_PTR GX_ASTR_PTR
#elif defined( _UNICODE)
#define GX_STR_PTR GX_WSTR_PTR
#else
#define GX_STR_PTR GX_ASTR_PTR
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*---------------- Copy_3DN[_public] ----------------*/
GX_WRAPPER_FUNC GX_LONG GX_WRAPPER_CALL
Copy_3DN(GX_VAR GX_OBJECT_PTR,
GX_CONST GX_HANDLE_PTR,
GX_CONST GX_HANDLE_PTR);
GX_STANDARD_FUNC GX_LONG GX_STANDARD_CALL
Std_Copy_3DN(GX_VAR GX_OBJECT_PTR,
GX_CONST GX_HANDLE_PTR,
GX_CONST GX_HANDLE_PTR);
...hundreds more like this
This yields a whole bunch of "expected initializer before " errors.
I've had some success by redefining the first 4 defines like this:
#ifdef __GNUC__
#define GX_WRAPPER_FUNC __attribute__ ((dllexport))
#define GX_STANDARD_FUNC
#define GX_WRAPPER_CALL
#define GX_STANDARD_CALL
#else
#define GX_WRAPPER_FUNC __declspec(dllexport)
#define GX_STANDARD_FUNC
#define GX_WRAPPER_CALL _cdecl
#define GX_STANDARD_CALL _stdcall
#endif
but it barfs later on when it encounters
GX_WRAPPER_FUNC GX_LONG GX_WRAPPER_CALL
RegisterResourceTracking_GEO(GX_VAR GX_OBJECT_PTR,
GX_CONST GX_LONG_PTR,
GX_OBJECT_PTR,
void (_stdcall *param3)(void*));
I would really like to use these headers WITHOUT editing them, and I've seen some references that suggest the correct choice of gcc distro might support this syntax, but I've tried a number already with no luck. I've tried both the i686 and x86-64 variants of MinGW-w64 and Nuwen and TDM. I'm not concerned with cross platform issues as the host app is Windows only anyways, and for my own stubborn reasons I don't want to give up and switch to MSVC.
So, is there a gcc distro which will support this syntax? If not, what is the path of least resistance?
cheers
As a workaround, you can expand your set of macro definitions to cover the keywords gcc doesn't recognize:
#ifdef __GNUC__
#define _cdecl __attribute__((cdecl))
#define __cdecl __attribute__((cdecl))
#define _stdcall __attribute__((stdcall))
#define __stdcall __attribute__((stdcall))
#define GX_WRAPPER_FUNC __attribute__ ((dllexport))
#else
#define GX_WRAPPER_FUNC __declspec(dllexport)
#endif
As a bonus, those make the original definitions here work:
#define GX_STANDARD_FUNC
#define GX_WRAPPER_CALL _cdecl
#define GX_STANDARD_CALL _stdcall
(FWIW, note that this is possible because most MSVC extensions are new simple keywords, from the space of identifiers reserved to the implementation. gcc's multi-token __attribute__(()) magic makes mapping in the reverse direction completely impossible. So any time you write code using gcc non-portable features, hide them behind macros.)
Related
I want to build a dll which can be used by any c++ and c# application can use. I installed cLion on mac and started a new project as c++ library.
I wrote some lines of code in the header file. Since I want to export my functions, I used __fdeclspec
But it is throwing me the error '__declspec' attributes are not enabled; use '-fdeclspec' or '-fms-extensions' to enable support for __declspec attributes
My code is
#pragma once
#ifdef MATHLIBRARY_EXPORTS
#define MATHLIBRARY_API __declspec(dllexport)
#else
#define MATHLIBRARY_API __declspec(dllimport)
#endif
extern "C" MATHLIBRARY_API void fibonacci_init(
const unsigned long long a, const unsigned long long b);
extern "C" MATHLIBRARY_API bool fibonacci_next();
extern "C" MATHLIBRARY_API unsigned long long fibonacci_current();
extern "C" MATHLIBRARY_API unsigned fibonacci_index();
How to fix this error so that I can build the solution?
You can use the following preprocessor checks to make a cross-platform macro for the export semantics:
#if defined(_MSC_VER)
#define MY_LIB_API __declspec(dllexport) // Microsoft
#elif defined(__GNUC__)
#define MY_LIB_API __attribute__((visibility("default"))) // GCC
#else
#define MY_LIB_API // Most compilers export all the symbols by default. We hope for the best here.
#pragma warning Unknown dynamic link import/export semantics.
#endif
So, in your code it would be:
#pragma once
#if defined(_MSC_VER)
#define MATHLIBRARY_API __declspec(dllexport) // Microsoft
#elif defined(__GNUC__)
#define MATHLIBRARY_API __attribute__((visibility("default"))) // GCC
#else
#define MATHLIBRARY_API // Most compilers export all the symbols by default. We hope for the best here.
#pragma warning Unknown dynamic link import/export semantics.
#endif
extern "C" MATHLIBRARY_API void fibonacci_init(
const unsigned long long a, const unsigned long long b);
extern "C" MATHLIBRARY_API bool fibonacci_next();
extern "C" MATHLIBRARY_API unsigned long long fibonacci_current();
extern "C" MATHLIBRARY_API unsigned fibonacci_index();
I understand that this error is typically a syntax problem. I've gone through this with a fine toothcomb and can't spot it. The example below is whittled down to a couple of files which display the problem. The header files describe an API that is provided as a couple of lib files which I've referenced in the Eclipse project, but just trying to compile the following from the command line gives the same error.
I have several chained includes before getting to the first function declaration which throws an "expected initializer" error, along with every other declaration that follows.
main.cpp
#include <iostream>
#include <string>
#include <windows.h>
#include "defn.h"
using namespace std;
int main()
{
cout << "hello world" << endl;
return 0;
}
defn.h
#ifndef GEO_DEFINITIONS_H_INCLUDED
#define GEO_DEFINITIONS_H_INCLUDED
#include <iostream>
#include <string>
#define C_MICROSOFT
#define _UNICODE
#include "gxlib.h"
#endif // GEO_DEFINITIONS_H_INCLUDED
gxlib.h
#pragma once
#include <windows.h>
#ifdef C_MICROSOFT
#define GX_WRAPPER_FUNC __declspec(dllexport)
#define GX_STANDARD_FUNC
#define GX_WRAPPER_CALL _cdecl
#define GX_STANDARD_CALL _stdcall
#define GX_OBJECT_PTR void*
#define GX_VAR
#define GX_CONST const
#define GX_VOID void
#define GX_LONG long
#define GX_DOUBLE double
#define GX_HANDLE long
#define GX_LONG_PTR long*
#define GX_DOUBLE_PTR double*
#define GX_HANDLE_PTR long*
#define GX_ASTR_PTR char*
#define GX_WSTR_PTR wchar_t*
#if defined(GEO_UTF8)
#define GX_STR_PTR GX_ASTR_PTR
#elif defined( _UNICODE)
#define GX_STR_PTR GX_WSTR_PTR
#else
#define GX_STR_PTR GX_ASTR_PTR
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*---------------- Copy_3DN[_public] ----------------*/
GX_WRAPPER_FUNC GX_LONG GX_WRAPPER_CALL
Copy_3DN(GX_VAR GX_OBJECT_PTR,
GX_CONST GX_HANDLE_PTR,
GX_CONST GX_HANDLE_PTR);
#ifdef __cplusplus
}
#endif
The command line and exact error is
c:\Code\CPP>g++ -std=c++0x -O0 -g3 -Wall -c -fmessage-length=0 -o main.o main.cpp
In file included from defn.h:11:0,
from main.cpp:4:
gxlib.h:55:1: error: expected initializer before 'Copy_3DN'
Copy_3DN(GX_VAR GX_OBJECT_PTR,
As I mentioned above, this is just an excerpt from a larger project that I'm building in Eclipse Mars using the MinGW-64 5.3 toolchain. Within Eclipse I've defined all of the include files and linked to the libraries, but this simple commandline example with everything in the same directory demonstrates the error.
I was lead to the answer by #SamVarshavchik's comment and this thread. The problem is the MSVC specific syntax
#define GX_WRAPPER_FUNC __declspec(dllexport)
#define GX_STANDARD_FUNC
#define GX_WRAPPER_CALL _cdecl
#define GX_STANDARD_CALL _stdcall
In my case the MSVC definitions are wrapped within the C_MICROSOFT #ifdef block, and that is the ONLY occurence of that definition, so the simplest solution is to remove the C_MICROSOFT define in defn.h and replace it with:
#ifdef __GNUC__
#define GX_WRAPPER_FUNC __attribute__ ((dllexport))
#define GX_STANDARD_FUNC
#define GX_WRAPPER_CALL __attribute__((cdecl))
#define GX_STANDARD_CALL __attribute__((stdcall))
#define _stdcall __attribute__((stdcall))
#define _cdecl __attribute__((cdecl))
#define GX_OBJECT_PTR void*
#define GX_VAR
#define GX_CONST const
#define GX_VOID void
#define GX_LONG long
#define GX_DOUBLE double
#define GX_HANDLE long
#define GX_LONG_PTR long*
#define GX_DOUBLE_PTR double*
#define GX_HANDLE_PTR long*
#define GX_ASTR_PTR char*
#define GX_WSTR_PTR wchar_t*
#define GX_STR_PTR GX_WSTR_PTR
#else
#define C_MICROSOFT
#endif
I used the answer from Determining 32 vs 64 bit in C++ to make this:
#ifndef AVUNA_CFG
#define AVUNA_CFG
#if _WIN32 || _WIN64
#if _WIN64
#define BIT64
#else
#define BIT32
#endif
#endif
// Check GCC
#if __GNUC__
#if __x86_64__ || __ppc64__
#define BIT64
#else
#define BIT32
#endif
#endif
#endif
However, this doesn't seem to work when specifying -m32 to GCC for cross compiling, so it always says BIT64. Is there any defines I can use for this purpose?
I ended up using an Eclipse-define because I have two different run configurations for 32/64-bit cross compile. Works well.
I am trying to pack some structs with Borland C++Builder (XE6) (in the future: bcc).
I am using a library which uses the following construct to create structs:
#ifdef _MSC_VER
#define PACKED_BEGIN __pragma(pack(push, 1))
#define PACKED
#define PACKED_END __pragma(pack(pop))
#elif defined(__GNUC__)
#define PACKED_BEGIN
#define PACKED __attribute__((__packed__))
#define PACKED_END
#endif
PACKED_BEGIN
struct PACKED {
short someSampleShort;
char sampleByte;
int sampleInteger;
} structType_t;
PACKED_END
The bcc compiler does not like the MSC __pragma, and does not like preprocessor directives inside of macros although it is described on their website:
#define GETSTD #include <stdio.h>
My Question is: Is there any possibility to use this construct with the Borland Compiler for packing a struct without using:
#pragma pack(1)
to pack every struct?
Are there any workarounds for this?
As you stated, C++Builder does not support preprocessor statements inside of macros. This is documented on Embarcadero's site:
#define (C++)
After each individual macro expansion, a further scan is made of the newly expanded text. This allows for the possibility of nested macros: The expanded text can contain macro identifiers that are subject to replacement. However, if the macro expands into what looks like a preprocessing directive, the directive will not be recognized by the preprocessor.
The reason for that is because the # character inside of a macro is reserved for the preprocessor's stringizing operator.
Some compilers, including MSVC, get around that restriction with the __pragma() compiler extension, or the C99/C++x0 _Pragma() extension. C++Builder's Windows 32bit compiler does not support either of those. However, its Windows 64bit and mobile compilers (which are all based on clang and support C++11) DO support both of them. So you can add support for those compilers in the macros like this:
#if defined(__BORLANDC__)
#if defined(__clang__)
#define PACKED_BEGIN __pragma(pack(push, 1))
#define PACKED
#define PACKED_END __pragma(pack(pop))
#else
#error Cannot define PACKED macros for this compiler
#endif
#elif defined(_MSC_VER)
#define PACKED_BEGIN __pragma(pack(push, 1))
#define PACKED
#define PACKED_END __pragma(pack(pop))
#elif defined(__GNUC__)
#define PACKED_BEGIN
#define PACKED __attribute__((__packed__))
#define PACKED_END
#else
#error PACKED macros are not defined for this compiler
#endif
If you want to support the C++Builder Windows 32bit compiler, you will have to move the logic into .h files that use #pragma for it, and then you can #include those files where needed (at least until the compiler is updated to support clang/C++11 - which Embarcadero is currently working on):
pack1_begin.h:
#if defined(__BORLANDC__)
#define PACKED_BEGIN
#define PACKED
#define PACKED_END
#pragma pack(push, 1)
#elif defined(_MSC_VER)
#define PACKED_BEGIN __pragma(pack(push, 1))
#define PACKED
#define PACKED_END __pragma(pack(pop))
#elif defined(__GNUC__)
#define PACKED_BEGIN
#define PACKED __attribute__((__packed__))
#define PACKED_END
#else
#error PACKED macros are not defined for this compiler
#endif
pack_end.h:
#if defined(__BORLANDC__)
#pragma pack(pop)
#endif
Then you can do this:
#include "pack1_begin.h"
PACKED_BEGIN
struct PACKED {
short someSampleShort;
char sampleByte;
int sampleInteger;
} structType_t;
PACKED_END
#include "pack_end.h"
If you take this approach, you can just drop PACKED_BEGIN/PACKED_END altogether:
pack1_begin.h:
#if defined(__BORLANDC__) || defined(_MSC_VER)
#define PACKED
#pragma pack(push, 1)
#elif defined(__GNUC__)
#define PACKED __attribute__((__packed__))
#else
#error PACKED macro is not defined for this compiler
#endif
pack_end.h:
#if defined(__BORLANDC__) || defined(_MSC_VER)
#pragma pack(pop)
#endif
#include "pack1_begin.h"
struct PACKED {
short someSampleShort;
char sampleByte;
int sampleInteger;
} structType_t;
#include "pack_end.h"
The standard offers one extra alternative for writing pragmas: the _Pragma operator:
#define PACKED_BEGIN _Pragma("pack(push, 1)")
#define PACKED
#define PACKED_END _Pragma("pack(pop)")
If the Borland compiler supports it, it should work.
I've been trying to get DirectX 11 to compile on MinGW. So far the only problem I'm having is that the headers are giving me errors saying that certain DirectX related stuff isn't defined.
So far I linked the libraries with -mwindows, -ld3d11, -d3dx11, and -ld3dx10. All the headers and libraries are in the default folders for the compiler.
I also did this before including the DirectX headers (this is needed for MinGW):
#define __in
#define __out
#define __inout
#define __in_bcount(x)
#define __out_bcount(x)
#define __in_ecount(x)
#define __out_ecount(x)
#define __in_ecount_opt(x)
#define __out_ecount_opt(x)
#define __in_bcount_opt(x)
#define __out_bcount_opt(x)
#define __in_opt
#define __inout_opt
#define __out_opt
#define __out_ecount_part_opt(x,y)
#define __deref_out
#define __deref_out_opt
#define __RPC__deref_out
#include "stdint.h"
typedef uint8_t UINT8;
I'm going to assume I did everything correct, but I get errors such as 'ID3D11DeviceContext' was not declared in this scope and 'pContext' was not declared in this scope. I don't know why it's doing this. Did I miss a step?