Check a __declspec macro in preprocessor - c++

If I have SOME_MACRO which is defined as either __declspec(dllimport) or __declspec(dllexport), is there a way to check at compile time which one is being used?
I.e. something like this:
#if SOME_MACRO == __declspec(dllimport)
// do something
#else
// do something else
#endif
UPD.
Looking at the answers I'm getting I guess I should be more specific in why I need this.
I'm trying to compile a rather big 3rd party library, which has a function declared as dllexport in most parts of their code where it's included. There's however one component in which it's a dllimport.
I need to modify the declaration slighly for the dllimport case. The switch between the two declarations is not very simple, it is a result of quite a deep tree of #ifdef instructions spread across several files. In principle I could dig this info out form these instructions, but to be sure I did it correctly I'd have to try and compile the whole library under several different configurations (each compilation taking a couple hours).
If on the other hand there was a simple way check whether their SOME_MACRO is evaluated to import or export, I could test this on a small program quickly and safely put that inside the library.

You cannot use
#if SOME_MACRO == __declspec(dllimport)
__declspec(dllimport) is not a valid token for a preprocessor expression.
Your best option is to use another preprocessor macro, such as:
// Are we building the DLL?
#if defined(BUILD_DLL)
// Yes, we are.
#define SOME_MACRO __declspec(dllexport)
#else
// No. We are using the DLL
#define SOME_MACRO __declspec(dllimport)
#endif
Now, you can use:
#if defined(BUILD_DLL)
to include conditional code depending on whether you are building the DLL or using the DLL.
Practically speaking, that ends to be a little bit more involved.
Most projects have more than one DLL. BUILD_DLL is not going to work. You will need BUILD_xxx_DLL for each DLL you build. Let's say you have two DLLs, utility and core. and an application that depends on both.
You may also need to create a static library.
You will need something like the following in every public .h file of the utility library.
#if defined(BUILD_UTILITY_STATIC)
#define UTLIITY_EXPORT
#elif defined(BUILD_UTILITY_DLL)
#define UTLIITY_EXPORT__declspec(dllexport)
#else
#define UTLIITY_EXPORT__declspec(dllimport)
#endif
Of course, you don't want to have to repeat the same code in lots of .h files. You will create a .h file that contains the above and #include that in all other .h files.
When building utility.dll, you will need to define BUILD_UTILITY_DLL and leave BUILD_UTILITY_STATIC undefined.
When building utllity.lib (static library), you will need to define BUILD_UTILITY_STATIC and leave BUILD_UTILITY_DLL undefined.
Users of utility.dll will leave BUILD_UTILITY_STATIC as well as BUILD_UTILITY_DLL undefined.
Users of utility.lib (static library) will need to define BUILD_UTILITY_STATIC and leave BUILD_UTILITY_DLL undefined.
You will need a similar file for core.dll and core.lib.

The macro is named by you the DLL creator.
You want a header file that works in export or import mode.
A C/C++ file will be used, to create a program, to build the DLL (export).
Other C/C++ files will be used to call the DLL (import functions).
In the build implementation file a macro, that you name, is defined before the inclusion of the header.
e.g.
#define DLLNAME_BUILD_DLL
#include "dll_header.h"
In the header, if the macro is defined, the mode is set to export. When using the DLL the macro is not defined and the functions are imported.

Related

Getting around __declspec(dllimport) in windows to linux project conversion

Im in the process of converting a visual studio c++ framework over into a linux build, and in the process of eliminating windows dependencies I ran into a whole bunch of __declspec(dllimport) calls in some header files. These header files define a bunch of functions and classes that are used in the source files, so theyre needed for the build.
Heres the exact lines that use the __declspec() call.
#ifndef UeiDaqAPI
#define UeiDaqAPI __declspec(dllimport)
#endif
UeiDaqAPI is the collection of classes and functions that all the source files use. The declspec call, from what I understand, links the functions/classes defined in the current .h file to the dynamic library "UeiDaqAPI"
__declspec(dllimport) is not supported by linux, so ive tried a "workaround" using dlopen(). For some more background information, about 40 header files use the above __declspec() call, so testing any workaround is very tedious. I was given a dynamic library for linux, in the .so format that I'm supposed to use.
I found an example of using dlopen(path-to-library) that should allow me to get around the __declspec() call but I am unsure how to get it working correctly. So far I have tried following the example, and changed all 40 or so header files and replaced the __declspec() call with the following:
#ifndef UeiDaqAPI
string nameOfLibToLoad("path/to/lib/lib.so");
UeiDaqAPI = dlopen(nameOfLibToLoad.c_str(), RTLD_LAZY);
if (!lib_handle) {
cerr << "Cannot load library: " << dlerror() << endl;
}
#endif
This however, I get errors stating that function calls that ARE defined in the header files were not defined, I suspect this is because they dont get added to the .so library, but Im not sure.
Id like some help either with implementing the above workaround, or, if there is a better way to get around the __declspec() call, then id like some pointers on where to start.
You shouldn't need to use dlopen, that is for dynamic loading (LoadLibrary/dlopen, GetProcAddress/dlsym, FreeLibrary/dlclose).
Instead as with Windows in the basic case it should be automatic, but the syntax is a little different.
Windows/MSVC generally only exports things from DLL's that it was specifically told to by __declspec(dllexport) and then when using the DLL only tries to link things explicitly told to by __declspec(dllimport).
GCC/Linux however by default (you can opt-in to an explicit export style) just exports everything in a .so, and when linking considers any object or library, so just declaring the function is enough, like for a static library or multiple C/C++ files.
void my_uei_daq_api_function(int a, int b);
Often in portable libraries there might be something along the lines of:
#if defined(_WIN32) && defined(MYLIB_DLL)
# ifdef MYLIB_BUILD
// Compiling a Windows DLL
# define MYLIB_EXPORT __declspec(dllexport)
# else
// Using a Windows DLL
# define MYLIB_EXPORT __declspec(dllimport)
# endif
// Windows or Linux static library, or Linux so
#else
# define MYLIB_EXPORT
#endif
Which is then used in the libraries headers:
MYLIB_EXPORT void my_uei_daq_api_function(int a, int b);

How does __declspec exactly work? [duplicate]

I had a question about DLL building / linking in Visual Studio 2005 and later. Basically my understanding and experience is this:
To build a DLL, I specify the project properties to build a DLL, and then I but __declspec(dllexport) in front of any functions or members that I want to publically expose from the DLL. Building the project will result in a DLL, a Lib, and a header file that can be deployed as say an API or something.
On the other end, to have your other compiled executable application dynamically link to the DLL and use its functions, you simply need to have your executable project include the header files and link with the small lib file that was created when the DLL was built. As long and the compiled application can find the DLL, everything will work.
That has been my experience and that is also how the Microsoft DLL building tutorial described everything on MSDN. I am wondering: is this standard practice? When would you ever need to use __declspec(dllimport) anywhere? Am I missing something?
Thanks!
Yes you would use __declspec(dllimport) and you generally have a macro that controls whether a source file either exports (if it's part of your DLL) or imports (if it's part of the using-executable) symbols.
In your DLL you can set a manifest constant to the build settings of some sort, say 'BUILDING_MY_DLL' and then create the macro like this within your header file:
#ifdef BUILDING_MY_DLL
#define MY_DLL_EXPORT __declspec(dllexport)
#else
#define MY_DLL_EXPORT __declspec(dllimport)
#endif
and then decorate your exported functions like this:
MY_DLL_EXPORT int func(int y);
You can also export entire classes this way too:
class MY_DLL_EXPORT InterestingClass
{
...
};

Preprocessor identifier in front of function declarations in a header file

I was reading a header file and I noticed that the programmer has put a preprocessor identifier in front of the return values of functions in their declarations, as following.
#ifndef SAMPLE_API
#define SAMPLE_API
#endif
...
namespace SampleName
{
SAMPLE_API bool api_function();
...
}
What's the purpose of it and how does it work?
Edit: I am reading imgui.h from the IMGUI project.
By defining SAMPLE_API (on your compiler command line, in your Makefile / IDE environment etc.), you could add something to each function declaration in this header.
If you did not define SAMPLE_API, the first couple of lines...
#ifndef SAMPLE_API
#define SAMPLE_API
#endif
...make sure that SAMPLE_API is "defined away", i.e.
SAMPLE_API bool api_function();
...is preprocessed to...
bool api_function();
...so "nothing happens" (instead of "syntax error" when the compiler runs into SAMPLE_API and does not know what to do with it).
The usual reason for a construct like this SAMPLE_API symbol is to handle symbol export / import when building / using a library for Windows.
You would define SAMPLE_API to...
__declspec(dllexport) when building a library for Windows,
__declspec(dllimport) when using a library for Windows,
...so the symbols for the functions in question get exported / imported as necessary.
There are other things that could be done with such a preprocessor symbol (like deprecating functions, so that the linker will warn if they are being used), or other platform-specific stuff. But I would guess you're looking at dllexport / dllimport plumbing here.
In this particular case it does nothing. (Remember that the preprocessor does little more than trivial copying and pasting).
But, it might be useful in some instances to declare for example, a declspec for exporting a DLL function (in which case it would be #DEFINEd to something less trivial. Needless to say, that kind of thing is not formally part of the C++ standard, but rather is likely exploiting compiler extensions.

When is __declspec(dllimport) used? [duplicate]

I had a question about DLL building / linking in Visual Studio 2005 and later. Basically my understanding and experience is this:
To build a DLL, I specify the project properties to build a DLL, and then I but __declspec(dllexport) in front of any functions or members that I want to publically expose from the DLL. Building the project will result in a DLL, a Lib, and a header file that can be deployed as say an API or something.
On the other end, to have your other compiled executable application dynamically link to the DLL and use its functions, you simply need to have your executable project include the header files and link with the small lib file that was created when the DLL was built. As long and the compiled application can find the DLL, everything will work.
That has been my experience and that is also how the Microsoft DLL building tutorial described everything on MSDN. I am wondering: is this standard practice? When would you ever need to use __declspec(dllimport) anywhere? Am I missing something?
Thanks!
Yes you would use __declspec(dllimport) and you generally have a macro that controls whether a source file either exports (if it's part of your DLL) or imports (if it's part of the using-executable) symbols.
In your DLL you can set a manifest constant to the build settings of some sort, say 'BUILDING_MY_DLL' and then create the macro like this within your header file:
#ifdef BUILDING_MY_DLL
#define MY_DLL_EXPORT __declspec(dllexport)
#else
#define MY_DLL_EXPORT __declspec(dllimport)
#endif
and then decorate your exported functions like this:
MY_DLL_EXPORT int func(int y);
You can also export entire classes this way too:
class MY_DLL_EXPORT InterestingClass
{
...
};

Dynamic libraries; how to fix useless dependencies?

I have a bunch of Dll's in my project, using VStudio 9.0 compiler, pre-compiled headers are used for all my Dll's. The dll's loading process is done by implicit caller (.dll, .lib and header must be supplied).
I typically create a different macro definition file per dll, for instance if my current Dll is called MYMacroDll I add a file _MyMacroDll.h which contains:
#ifndef _MYMACRODLL_H_
#define _MYMACRODLL_H_
#ifdef _WIN32
#ifdef MYMACRODLL_EXPORTS
#define MYMACRODLL_API __declspec(dllexport)
#else
#define MYMACRODLL_API __declspec(dllimport)
#endif
#define MYMACRODLL_CALL __cdecl
#else
#define MYMACRODLL_API
#define MYMACRODLL_CALL
#endif
#endif
I know the code can be simplified but I keep the last defines for portability, at least, that's what I understood...
The pre-compiled header file pch.h, will always include the macro definition file _MyMacroDll.h, this makes things easier to me, 'cause later I can decide whether a new class or function will be interfaced or not. This so far works correct.
The confusion comes from using the dll interfaces in another dll; let's suppose a second dll ImageLoaderDll. This one uses instances or references of one (or several) of the interfaced classes/functions in _MyMacroDll. At first glance I guessed there was no need of including the _MyMacroDll.h, but when compiling the ImageLoaderDll it complains with
error C2470: '_AnInterfaceClassFromMyMacro' : looks like a function definition, but there is no parameter list; skipping apparent body
Then I have to include the _MyMacroDll.h in the pre-compiler header file of the other Dll, my project is becoming really messy and I find more and more useless dependencies.
What am doing wrong? Is there another way of setting up the macro definitions so I can avoid adding it to the client Dll's? Am not an expert regarding software design, but in this situation the more decoupled the better.
Hope my explanation was good enough.
If you are using the DLL interface from MyMacroDll in ImageLoaderDll, then you do have a dependency. ImageLoaderDll should include _MyMacroDll.h, otherwise you can't call its functions correctly. It's exactly the same as including <string.h> when you want to call strlen.