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
{
...
};
Related
I am working on a C++ (VS2017) project that uses a protobuf type I created.
However, this project requires a .dll of said protobuf type. The __declspec( dllexport ) in each class declaration are not there by default, and I read online that they can be added by generating the protobuf object with this command line:
--cpp_out=dllexport_decl=MY_EXPORT_MACRO:output/directory
No one has explained what MY_EXPORT_MACRO is or how to define it. When I first generated my protobuf objects I used the most basic line and it worked:
protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/my_file.proto
What and where is MY_EXPORT_MACRO and/or is there another way to make my protobuf files .dll compatible?
You know about __declspec( dllimport ) also, correct? What's the easiest way to use the same type definition while building the DLL (with dllexport annotations) and in DLL clients (with dllimport annotations)?
Having a macro to switch the annotation is an extremely common practice in Win32 DLL development of all sorts, not just for protobuf DLLs.
Usually the definition runs like this:
#if BUILD_DLLX
# define DLLX_API __declspec(dllexport)
#else
# pragma comment('lib', 'dllx.lib')
# define DLLX_API __declspec(dllimport)
#endif
And then you would use --cpp_out=dllexport_decl=DLLX_API:$DST_DIR so that the generated header files have DLLX_API inserted in the right places. Then build the DLL with /DBUILD_DLLX so it exports the types and functions.
Consumers of the DLL can #include the exact same header file, and with no /DBUILD_DLLX in their project configuration, they'll end up with imports.
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);
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
{
...
};
I generated a *.dll with VC++. When I want to use it, a *.lib is required. But I cannot find it. How to get the *.lib? Thanks.
Unless you specify otherwise, the .lib will be generated in the same directory as the .DLL.
If you're getting a dll but not a lib, chances are pretty good that somehow or other you're not actually exporting anything from the dll. In such a case, the linker will create the dll, but won't automatically create a matching import library.
This really depends on your project settings.
Take a look at *.vcprojx
and search for similar pattern:
<link>
<ImportLibrary>.\Release/yourlibrary.lib</ImportLibrary>
</link>
Usually, Visual Studio puts the .lib right next to the .dll file.
YOur case sounds like it wouldn't generate a .lib at all. When building libraries as dll, if you want to link to that library in another project (as opposed to using dllopen and the likes), you have to specify which functions should be exported to a lib. For this, you have to prepend all classes or functions you want to export with a __declspec(dllexport) when building the library, and __declspec(dllimport) when linking it.
What you often find is some macro like this:
#ifdef WIN32
#ifdef MYLIB_EXPORTS
#define MYLIBAPI __declspec(dllexport)
#else
#define MYLIBAPI __declspec(dllimport)
#endif
#else
#define MYLIBAPI
#endif
Then, when building the lib, you define the MYLIB_EXPORTS preprocessor, so that it exports, while linking against it imports. Your own Code could then look like this
class MYLIBAPI MyClass
{
public:
void SomeFunction()
}
MYLIBAPI void SomeGlobalFunction();
Now, MyClass and SomeGLobalFunction are exported when building, and occur in the lib file.
I have a dll with a class that define some methods and variables inside it. I marked it as
__declspec(dllexport)
and i imported the .h header inside a win32 application project in the same solution. I can use the functions but when I try to compile the project I have a lot of errors about external symbols not resolved. Why?
Please read about the standard way of using macros for this very common task here: http://wiki.tcl.tk/8721
The basic idea is that you define a macro, say MY_API like so:
#ifdef BUILD_MYAPI
# define MY_API __declspec(dllexport)
#else
# define MY_API __declspec(dllimport)
#endif
When you declare a function or a class in the header file you do this:
void MY_API myApiFunction(int x);
When you build your own dll which declares the body of the function, you add the definition of BUILD_MYAPI to the build. This makes all declerations to be dllexport
when you include the header from some other dll you don't add BUILD_MYAPI so the decelerations are dllimport
When compiling with visual studio, you can add a macro definition to the compilation without changing the source from project properties -> C/C++ -> Preprocesson -> Preprocessor definitions
For the application where you want to import that class, you will need to mark the class as
__declspec(dllimport)
Instead of dllexport.
You must also make sure to link with the import library of the DLL (a .lib file).