Handling Dll Exports
Overview
Both msvc and gcc have properties that you can enable on your functions and classes to enable them to hide or make public the symbols you wish to expose to the user of that library.
If you think of public/private for a class, but scale that up to public/private for a library, then you've got the idea.
Gcc by default, makes everything public, i.e. it exports its symbols. You can disable these exports and it will result in a minor speedup in linkage. Msvc on the other hand makes everything private. So if you take c++ library written with gcc and immediately compile that for windows, then it may compile, but you'll end up with a seemingly 'empty' dll.
This guide shows how to go about enabling these exports for dll's in a cross-platform way. For the purposes of this guide, we'll assume you are building a package called foo.
Import/Export Macros
When cmake makes a shared library, it will automatically add a definition to the compile step, -Dmy_package_EXPORTS. You can use this to trigger the required import/export functionality in your package.
Add cpp_common as a package dependency (if it already isn't requiring roscpp).
Create a header file: /include/foo/macros.h with the content
#ifndef FOO_MACROS_H_ #define FOO_MACROS_H_ #include <ros/macros.h> #ifdef ROS_BUILD_SHARED_LIBS // ros is being built around shared libraries #ifdef foo_EXPORTS // we are building a shared lib/dll #define FOO_DECL ROS_HELPER_EXPORT #else // we are using shared lib/dll #define FOO_DECL ROS_HELPER_IMPORT #endif #else // ros is being built around static libraries #define FOO_DECL #endif #endif
Proceed to prepend FOO_DECL before every element you wish to make public. Some examples from various parts of ros:
# global function in rostime/include/ros/duration.h ROSTIME_DECL void normalizeSecNSecSigned(int64_t& sec, int64_t& nsec);
# class in rostime/include/ros/duration.h class ROSTIME_DECL Duration : public DurationBase<Duration>
# global constant in rostime/include/ros/duration.h extern ROSTIME_DECL const Duration DURATION_MIN;
# template classes don't need any declaration template <typename Data> class DataException : public Exception {
What if I Don't Want Cpp_Common as a Dependency?
Cpp common just defines the ROS_HELPER_xxx macros which are easy to transfer across to your own project. Simply precede the previous definitions with something similar to that which is defined in cpp_common/include/ros/macros.h:
/* Windows import/export and gnu http://gcc.gnu.org/wiki/Visibility macros. */ #if defined(_MSC_VER) #define ROS_HELPER_IMPORT __declspec(dllimport) #define ROS_HELPER_EXPORT __declspec(dllexport) #define ROS_HELPER_LOCAL #elif __GNUC__ >= 4 #define ROS_HELPER_IMPORT __attribute__ ((visibility("default"))) #define ROS_HELPER_EXPORT __attribute__ ((visibility("default"))) #define ROS_HELPER_LOCAL __attribute__ ((visibility("hidden"))) #else #define ROS_HELPER_IMPORT #define ROS_HELPER_EXPORT #define ROS_HELPER_LOCAL #endif // Ignore warnings about import/exports when deriving from std classes. #ifdef _MSC_VER #pragma warning(disable: 4251) #pragma warning(disable: 4275) #endif