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();
Related
I am calling Matlab compiled DLLs from C++ code. I use Matab 2015b for development and Matlab 9.0 as runtime.
The following command was used in a Windows 10 64-bit machine to compile Matlab application
mcc -v -a .\+ismrmrd -W cpplib:libStdFourier -T link:lib StdFourier.m -d E:\dev\matlab\mfiles\StdFourier
The DLL call works fine in the development machine. But when I deploy it in another machine which runs on Windows 7 64-bit with Runtime 9.0 installed, the library fails to initialise. The runtime initialises successfully and following error occurs at library intialise method libStdFourierInitialize()
I use following code for initialising runtime and library:
mclmcrInitialize();
const char *rtOptions[3];
rtOptions[0] = "-singleCompThread";
rtOptions[1] = "-logfile";
rtOptions[2] = "matlogfile.txt";
if (!mclInitializeApplication(rtOptions,3))
{
std::cerr << "Could not initialize the application properly." << std::endl;
}
std::cout << "MCR initialized:" << mclIsMCRInitialized() << std::endl; //Returns true
std::cout << "Initialize libStdFourier" << << std::endl;
/* Call the library intialization routine and make sure that the
library was initialized properly. */
if(!libStdFourierInitialize())
{
fprintf(stderr,"Could not initialize the library.\n");
}
And the error console window
Code for the header:
#ifndef __libStdFourier_h
#define __libStdFourier_h 1
#if defined(__cplusplus) && !defined(mclmcrrt_h) && defined(__linux__)
# pragma implementation "mclmcrrt.h"
#endif
#include "mclmcrrt.h"
#include "mclcppclass.h"
#ifdef __cplusplus
extern "C" {
#endif
#if defined(__SUNPRO_CC)
/* Solaris shared libraries use __global, rather than mapfiles
* to define the API exported from a shared library. __global is
* only necessary when building the library -- files including
* this header file to use the library do not need the __global
* declaration; hence the EXPORTING_<library> logic.
*/
#ifdef EXPORTING_libStdFourier
#define PUBLIC_libStdFourier_C_API __global
#else
#define PUBLIC_libStdFourier_C_API /* No import statement needed. */
#endif
#define LIB_libStdFourier_C_API PUBLIC_libStdFourier_C_API
#elif defined(_HPUX_SOURCE)
#ifdef EXPORTING_libStdFourier
#define PUBLIC_libStdFourier_C_API __declspec(dllexport)
#else
#define PUBLIC_libStdFourier_C_API __declspec(dllimport)
#endif
#define LIB_libStdFourier_C_API PUBLIC_libStdFourier_C_API
#else
#define LIB_libStdFourier_C_API
#endif
/* This symbol is defined in shared libraries. Define it here
* (to nothing) in case this isn't a shared library.
*/
#ifndef LIB_libStdFourier_C_API
#define LIB_libStdFourier_C_API /* No special import/export declaration */
#endif
extern LIB_libStdFourier_C_API
bool MW_CALL_CONV libStdFourierInitializeWithHandlers(
mclOutputHandlerFcn error_handler,
mclOutputHandlerFcn print_handler);
extern LIB_libStdFourier_C_API
bool MW_CALL_CONV libStdFourierInitialize(void);
extern LIB_libStdFourier_C_API
void MW_CALL_CONV libStdFourierTerminate(void);
extern LIB_libStdFourier_C_API
void MW_CALL_CONV libStdFourierPrintStackTrace(void);
extern LIB_libStdFourier_C_API
bool MW_CALL_CONV mlxStdFourier(int nlhs, mxArray *plhs[], int nrhs, mxArray *prhs[]);
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
/* On Windows, use __declspec to control the exported API */
#if defined(_MSC_VER) || defined(__BORLANDC__)
#ifdef EXPORTING_libStdFourier
#define PUBLIC_libStdFourier_CPP_API __declspec(dllexport)
#else
#define PUBLIC_libStdFourier_CPP_API __declspec(dllimport)
#endif
#define LIB_libStdFourier_CPP_API PUBLIC_libStdFourier_CPP_API
#else
#if !defined(LIB_libStdFourier_CPP_API)
#if defined(LIB_libStdFourier_C_API)
#define LIB_libStdFourier_CPP_API LIB_libStdFourier_C_API
#else
#define LIB_libStdFourier_CPP_API /* empty! */
#endif
#endif
#endif
extern LIB_libStdFourier_CPP_API void MW_CALL_CONV StdFourier(int nargout, mwArray& bufferQ, mwArray& imageQ, const mwArray& xmlstr, const mwArray& recon_data);
#endif
#endif
Thanks.
I'm trying to create a C++ dll. I have followed the msdn tutorial but I can't compile my dll correctly.
The problem is that any function is exported. I have tested it with dumpbin.exe tool and nm tool.
In both cases, there is no detected symbols.
Here is the code of this library:
Header file:
#ifndef NLIB_H
#define NLIB_H
#ifdef _WINDLL
#define NLIB_EXPORTS __declspec( dllexport )
#else
#define NLIB_EXPORTS __declspec( dllimport )
#endif
#ifdef __cplusplus
extern "C"{
#endif
NLIB_EXPORTS int fun1(int n);
#ifdef __cplusplus
}
#endif
#endif
Source code file:
#include "nlib.h"
int fun1(int n) {
return 100;
}
I have found the error. It's necessary to add NLIB_EXPORTS to the *.c file also, like this:
#include "nlib.h"
NLIB_EXPORTS int fun1(int n) {
return 100;
}
I have a class which header looks like this:
class MYCLASS_DECLSPEC MyClass
{
MyClass(int x);
....
static const MyClass Zero;
}
On the implementation file I initialized the static const member:
const A A::Zero(0);
Now I want to compile this code sometimes as a DLL and sometimes as static library. The common practice is to define MYCLASS_DECLSPEC like this:
#ifdef BUILDING_MYDLL
#define MYCLASS_DECLSPEC __declspec(dllexport)
#else
#define MYCLASS_DECLSPEC __declspec(dllimport)
#endif
When I compile this code as DLL (with BUILDING_MYDLL defined) everything is working fine. But when I compile this code as static library (without BUILDING_MYDLL defined) I get the following error:
error: definition of static data member 'MyClass::Zero' of dllimport'd class
If I totally remove the __declspec(dllimport) the code compiles successfully as a static library.
I'm using mingw32 compiler on Windows 7.
Can someone explain why it happens and how to solve it?
I would think we put #defines in another #define:
#ifdef _DLL
#ifdef BUILDING_MYDLL
#define MYCLASS_DECLSPEC __declspec(dllexport)
#else
#define MYCLASS_DECLSPEC __declspec(dllimport)
#endif
#else
#define MYCLASS_DECLSPEC
#endif
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.)
I have a header that I want to include from .c and .cpp files.
so I know about name mangling and extern "C" so...
#ifdef __cplusplus
extern "C"
{
int isPrime(int64_t p);
}
#endif
but when I include this in the .c file it doesn't see the function because of the #ifdef __cplusplus
so then I end up making 2 copies:
#ifdef __cplusplus
extern "C"
{
int isPrime(int64_t p);
}
#else
int isPrime(int64_t p);
#endif
is there a better way to do this... I thought about making another header called prototypes.h and including that in those 2 places... but is there something simple I am missing?
Yes, there is a better way. People are usually doing this :
#ifdef __cplusplus
extern "C"
{
#endif
int isPrime(int64_t p);
#ifdef __cplusplus
}
#endif
If you want to do something different in c and c++ (like for example this) then you can use the 2nd syntax in your question.
Another way of doing this is as follows
// intro
#ifdef __cplusplus
#define EXTERN_C extern "C"
#else
#define EXTERN_C
#endif
// content
EXTERN_C int isPrime(int64_t p);
// many other functions declared with EXTERN_C
Normally the "intro" part is placed in some common header file for everyone to use.
The advantage of this format is that each declaration is immediately seen as extern "C". A reader doesn't have to search around for possible extern "C" {
#ifdef __cplusplus
extern "C"
{
#endif
int isPrime(int64_t p);
#ifdef __cplusplus
}
#endif
That way, you can extend the int isPrime(int64_t p); part arbitrarily without repeating it in your #ifdef and #else cases.