Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stefanofiorentino/f49e459210b462b797ca884c05040887 to your computer and use it in GitHub Desktop.
Save stefanofiorentino/f49e459210b462b797ca884c05040887 to your computer and use it in GitHub Desktop.
From c1bc3bf02474fc4aa44e81b153e49b039a1f74b7 Mon Sep 17 00:00:00 2001
From: "Fiorentino Ing. Stefano" <stefano.fiore84@gmail.com>
Date: Fri, 22 May 2020 18:40:28 +0200
Subject: [PATCH] (extern) explicit instantiation of a type_factory
Signed-off-by: Fiorentino Ing. Stefano <stefano.fiore84@gmail.com>
---
.github/workflows/build.yml | 45 +-
...41fa871a7e818a75275294b82d2b3555ca79.patch | 1606 +++++++++++++++++
src/CMakeLists.txt | 15 +-
src/uvw.hpp | 241 +++
src/uvw/async.h | 8 +-
src/uvw/check.h | 8 +-
src/uvw/config.h | 38 +-
src/uvw/dns.h | 29 +-
src/uvw/emitter.h | 37 +-
src/uvw/fs.h | 11 +-
src/uvw/fs_event.h | 10 +-
src/uvw/fs_poll.h | 9 +-
src/uvw/handle.hpp | 16 +-
src/uvw/idle.h | 9 +-
src/uvw/lib.h | 7 +-
src/uvw/loop.h | 15 +-
src/uvw/pipe.h | 7 +-
src/uvw/poll.h | 10 +-
src/uvw/prepare.h | 9 +-
src/uvw/process.h | 10 +-
src/uvw/request.hpp | 5 +
src/uvw/resource.hpp | 5 +
src/uvw/signal.h | 9 +-
src/uvw/stream.cpp | 13 +
src/uvw/stream.h | 70 +-
src/uvw/tcp.h | 31 +-
src/uvw/thread.h | 21 +-
src/uvw/timer.h | 9 +-
src/uvw/tty.h | 9 +-
src/uvw/type_factory/type_factory.cpp | 264 +++
src/uvw/type_factory/type_factory.h | 18 +
src/uvw/udp.h | 89 +-
src/uvw/underlying_type.hpp | 5 +
src/uvw/util.cpp | 4 +
src/uvw/util.h | 38 +-
src/uvw/work.h | 9 +-
test/CMakeLists.txt | 2 +-
test/main.cpp | 186 +-
test/uvw/emitter.cpp | 8 -
test/uvw/handle.cpp | 12 -
test/uvw/thread.cpp | 1 +
test/uvw/tty.cpp | 1 -
test/uvw/util.cpp | 1 -
43 files changed, 2616 insertions(+), 334 deletions(-)
create mode 100644 5ca341fa871a7e818a75275294b82d2b3555ca79.patch
create mode 100644 src/uvw/type_factory/type_factory.cpp
create mode 100644 src/uvw/type_factory/type_factory.h
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 0591182..055ff7e 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -3,31 +3,6 @@ name: build
on: [push, pull_request]
jobs:
-
- linux:
- timeout-minutes: 60
- runs-on: ubuntu-latest
-
- strategy:
- matrix:
- compiler: [g++, clang++]
- mode: [-DBUILD_UVW_LIBS=ON, -DBUILD_UVW_LIBS=OFF]
-
- steps:
- - uses: actions/checkout@v1
- - name: Compile tests
- working-directory: build
- env:
- CXX: ${{ matrix.compiler }}
- run: |
- cmake ${{ matrix.mode }} -DBUILD_TESTING=ON -Dlibuv_buildtests=OFF ..
- make -j4
- - name: Run tests
- working-directory: build
- env:
- CTEST_OUTPUT_ON_FAILURE: 1
- run: ctest --timeout 5 -C Debug -j4
-
windows:
timeout-minutes: 60
runs-on: windows-latest
@@ -35,7 +10,7 @@ jobs:
strategy:
matrix:
generator: [Visual Studio 16 2019]
- mode: [-DBUILD_UVW_LIBS=ON, -DBUILD_UVW_LIBS=OFF]
+ mode: [-DBUILD_UVW_LIBS=ON]
steps:
- uses: actions/checkout@v1
@@ -43,20 +18,4 @@ jobs:
working-directory: build
run: |
cmake ${{ matrix.mode }} -DBUILD_TESTING=ON -Dlibuv_buildtests=OFF -DCMAKE_CXX_FLAGS=/W1 -G"${{ matrix.generator }}" ..
- cmake --build . -j 4
-
- macos:
- timeout-minutes: 60
- runs-on: macOS-latest
-
- strategy:
- matrix:
- mode: [-DBUILD_UVW_LIBS=ON, -DBUILD_UVW_LIBS=OFF]
-
- steps:
- - uses: actions/checkout@v1
- - name: Compile tests
- working-directory: build
- run: |
- cmake ${{ matrix.mode }} -DBUILD_TESTING=ON -Dlibuv_buildtests=OFF ..
- make -j4
+ cmake --build . -j 4
\ No newline at end of file
diff --git a/5ca341fa871a7e818a75275294b82d2b3555ca79.patch b/5ca341fa871a7e818a75275294b82d2b3555ca79.patch
new file mode 100644
index 0000000..2d7c143
--- /dev/null
+++ b/5ca341fa871a7e818a75275294b82d2b3555ca79.patch
@@ -0,0 +1,1606 @@
+From 5ca341fa871a7e818a75275294b82d2b3555ca79 Mon Sep 17 00:00:00 2001
+From: test <test@test.test>
+Date: Sun, 17 May 2020 02:22:29 +0200
+Subject: [PATCH] shared libs: export classes with functions implemented in
+ .cpp files
+
+When building a DLL on Windows or building a shared library with
+`-fvisibility=hidden` on Unix, class with functions implemented in a cpp
+file must be exported.
+
+This mean `__declspec(dllexport)` on Windows, and
+`__attribute__((visibility(default)))` on Unix.
+
+Changes made:
+ - `UVW_EXTERN` on all non templated classes.
+
+ - Declare `UVW_EXTERN` in config.h.
+
+ - Put `UVW_EXTERN` on all extern explicit template instantiations.
+
+ - Put `UVW_EXTERN` on instantiation of `Flags<T>` from an exported template.
+ MSVC was throwing a `C4251` warning for these, so I'm exported them too
+ via an explicit template instantiation. This is not required for the code
+ to link in fact.
+
+ - Also add `UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE()` for MSVC as it
+ outputs many `C4251` warnings when an exported class uses a non exported
+ template in the standard library. This means the user of the DLL must use
+ similar enough compiler and flags so the C++ ABI is the same.
+ There are these macro in all headers so the warning is still enabled for
+ user code, if the user happen to use `__declspec(dllexport)` too.
+
+ - Almost all exported classes derive from a template class. This doesn't
+ trigger warning `C4275` because the base template class use the derived
+ class in its template arguments. See last point here: https://docs.microsoft.com/en-us/cpp/cpp/general-rules-and-limitations?view=vs-2019
+
+ - Change tests link libraries to use `uvw-shared` and `uv-shared` instead.
+ So this will test that functions are really available from the DLL/.so.
+
+ - Add CMake code to declare `USING_UVW_SHARED` or `BUILDING_UVW_SHARED` as
+ appropriate.
+
+ - Enable `CXX_VISIBILITY_HIDDEN` so only explicitly exported symbols are
+ exported.
+
+Currently not working because of static variables in `Emitter<>::next_type()`
+and `Emitter<>::event_type<>()`.
+
+Fixes: #196
+---
+ src/CMakeLists.txt | 14 +++++-
+ src/uvw/async.h | 8 +++-
+ src/uvw/check.h | 8 +++-
+ src/uvw/config.h | 38 +++++++++++++++-
+ src/uvw/dns.h | 29 +++++++-----
+ src/uvw/emitter.h | 15 ++++++-
+ src/uvw/fs.h | 11 +++--
+ src/uvw/fs_event.h | 10 ++++-
+ src/uvw/fs_poll.h | 9 +++-
+ src/uvw/handle.hpp | 7 ++-
+ src/uvw/idle.h | 9 +++-
+ src/uvw/lib.h | 7 ++-
+ src/uvw/loop.h | 15 ++++---
+ src/uvw/pipe.h | 7 ++-
+ src/uvw/poll.h | 10 ++++-
+ src/uvw/prepare.h | 9 +++-
+ src/uvw/process.h | 10 ++++-
+ src/uvw/request.hpp | 5 +++
+ src/uvw/resource.hpp | 5 +++
+ src/uvw/signal.h | 9 +++-
+ src/uvw/stream.h | 19 +++++---
+ src/uvw/tcp.h | 31 +++++++------
+ src/uvw/thread.h | 21 +++++----
+ src/uvw/timer.h | 9 +++-
+ src/uvw/tty.h | 9 +++-
+ src/uvw/udp.h | 89 ++++++++++++++++++++-----------------
+ src/uvw/underlying_type.hpp | 5 +++
+ src/uvw/util.cpp | 4 ++
+ src/uvw/util.h | 38 +++++++++-------
+ src/uvw/work.h | 9 +++-
+ test/CMakeLists.txt | 4 +-
+ 31 files changed, 334 insertions(+), 139 deletions(-)
+
+diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
+index 25e6c12..af19cd6 100644
+--- a/src/CMakeLists.txt
++++ b/src/CMakeLists.txt
+@@ -74,8 +74,20 @@ add_uvw_library(uvw-static)
+ add_library(uvw-shared SHARED)
+ add_library(uvw::uvw-shared ALIAS uvw-shared)
+ target_link_libraries(uvw-shared PUBLIC uv::uv-shared)
+-set_target_properties(uvw-shared PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${UVW_VERSION_MAJOR} EXCLUDE_FROM_DEFAULT_BUILD 1)
++set_target_properties(uvw-shared PROPERTIES
++ VERSION ${PROJECT_VERSION}
++ SOVERSION ${UVW_VERSION_MAJOR}
++ EXCLUDE_FROM_DEFAULT_BUILD 1
++ C_VISIBILITY_PRESET hidden
++ CXX_VISIBILITY_PRESET hidden
++)
+ add_uvw_library(uvw-shared)
++target_compile_definitions(uvw-shared
++ INTERFACE
++ USING_UVW_SHARED=1
++ PRIVATE
++ BUILDING_UVW_SHARED=1
++)
+
+ #
+ # Install targets
+diff --git a/src/uvw/async.h b/src/uvw/async.h
+index e326bac..4e6f4e3 100644
+--- a/src/uvw/async.h
++++ b/src/uvw/async.h
+@@ -5,7 +5,9 @@
+ #include <uv.h>
+ #include "handle.hpp"
+ #include "loop.h"
++#include "config.h"
+
++UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
+
+ namespace uvw {
+
+@@ -15,7 +17,7 @@ namespace uvw {
+ *
+ * It will be emitted by AsyncHandle according with its functionalities.
+ */
+-struct AsyncEvent {};
++struct UVW_EXTERN AsyncEvent {};
+
+
+ /**
+@@ -26,7 +28,7 @@ struct AsyncEvent {};
+ *
+ * To create an `AsyncHandle` through a `Loop`, no arguments are required.
+ */
+-class AsyncHandle final: public Handle<AsyncHandle, uv_async_t> {
++class UVW_EXTERN AsyncHandle final : public Handle<AsyncHandle, uv_async_t> {
+ static void sendCallback(uv_async_t *handle);
+
+ public:
+@@ -63,4 +65,6 @@ class AsyncHandle final: public Handle<AsyncHandle, uv_async_t> {
+ #include "async.cpp"
+ #endif
+
++UVW_MSVC_WARNING_POP();
++
+ #endif // UVW_ASYNC_INCLUDE_H
+diff --git a/src/uvw/check.h b/src/uvw/check.h
+index 4d3e571..79f6d37 100644
+--- a/src/uvw/check.h
++++ b/src/uvw/check.h
+@@ -5,7 +5,9 @@
+ #include <uv.h>
+ #include "handle.hpp"
+ #include "loop.h"
++#include "config.h"
+
++UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
+
+ namespace uvw {
+
+@@ -15,7 +17,7 @@ namespace uvw {
+ *
+ * It will be emitted by CheckHandle according with its functionalities.
+ */
+-struct CheckEvent {};
++struct UVW_EXTERN CheckEvent {};
+
+
+ /**
+@@ -26,7 +28,7 @@ struct CheckEvent {};
+ *
+ * To create a `CheckHandle` through a `Loop`, no arguments are required.
+ */
+-class CheckHandle final: public Handle<CheckHandle, uv_check_t> {
++class UVW_EXTERN CheckHandle final : public Handle<CheckHandle, uv_check_t> {
+ static void startCallback(uv_check_t *handle);
+
+ public:
+@@ -60,4 +62,6 @@ class CheckHandle final: public Handle<CheckHandle, uv_check_t> {
+ #include "check.cpp"
+ #endif
+
++UVW_MSVC_WARNING_POP();
++
+ #endif // UVW_CHECK_INCLUDE_H
+diff --git a/src/uvw/config.h b/src/uvw/config.h
+index cfee0c9..429f8fe 100644
+--- a/src/uvw/config.h
++++ b/src/uvw/config.h
+@@ -1,12 +1,48 @@
+ #ifndef UVW_CONFIG_H
+ #define UVW_CONFIG_H
+
++#if defined(BUILDING_UVW_SHARED) && defined(USING_UVW_SHARED)
++#error "Define either BUILDING_UVW_SHARED or USING_UVW_SHARED, not both."
++#endif
+
+ #ifndef UVW_AS_LIB
+ #define UVW_INLINE inline
++#define UVW_EXTERN /* nothing */
++#else /* UVW_AS_LIB */
++#define UVW_INLINE /* nothing */
++
++#ifdef _WIN32
++/* Windows - set up dll import/export decorators. */
++#if defined(BUILDING_UVW_SHARED)
++/* Building shared library. */
++#define UVW_EXTERN __declspec(dllexport)
++#elif defined(USING_UVW_SHARED)
++/* Using shared library. */
++#define UVW_EXTERN __declspec(dllimport)
++#else
++/* Building static library. */
++#define UVW_EXTERN /* nothing */
++#endif
++#elif __GNUC__ >= 4
++#define UVW_EXTERN __attribute__((visibility("default")))
+ #else
+-#define UVW_INLINE
++#define UVW_EXTERN /* nothing */
+ #endif
+
++#endif /* UVW_AS_LIB */
++
++#if defined(_MSC_VER) && defined(UVW_AS_LIB)
++/*
++ * C4251: 'type' : class 'type1' needs to have dll-interface to be used by clients of class 'type2'
++ */
++#define UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE() \
++ __pragma(warning(push)) \
++ __pragma(warning(disable: 4251))
++#define UVW_MSVC_WARNING_POP() \
++ __pragma(warning(pop))
++#else
++#define UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE()
++#define UVW_MSVC_WARNING_POP()
++#endif
+
+ #endif
+diff --git a/src/uvw/dns.h b/src/uvw/dns.h
+index e9b2e86..db90ddd 100644
+--- a/src/uvw/dns.h
++++ b/src/uvw/dns.h
+@@ -9,6 +9,9 @@
+ #include "request.hpp"
+ #include "util.h"
+ #include "loop.h"
++#include "config.h"
++
++UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
+
+
+ namespace uvw {
+@@ -19,7 +22,7 @@ namespace uvw {
+ *
+ * It will be emitted by GetAddrInfoReq according with its functionalities.
+ */
+-struct AddrInfoEvent {
++struct UVW_EXTERN AddrInfoEvent {
+ using Deleter = void(*)(addrinfo *);
+
+ AddrInfoEvent(std::unique_ptr<addrinfo, Deleter> addr);
+@@ -39,7 +42,7 @@ struct AddrInfoEvent {
+ *
+ * It will be emitted by GetNameInfoReq according with its functionalities.
+ */
+-struct NameInfoEvent {
++struct UVW_EXTERN NameInfoEvent {
+ NameInfoEvent(const char *host, const char *serv);
+
+ /**
+@@ -68,7 +71,7 @@ struct NameInfoEvent {
+ *
+ * To create a `GetAddrInfoReq` through a `Loop`, no arguments are required.
+ */
+-class GetAddrInfoReq final: public Request<GetAddrInfoReq, uv_getaddrinfo_t> {
++class UVW_EXTERN GetAddrInfoReq final: public Request<GetAddrInfoReq, uv_getaddrinfo_t> {
+ static void addrInfoCallback(uv_getaddrinfo_t *req, int status, addrinfo *res);
+ void nodeAddrInfo(const char *node, const char *service, addrinfo *hints = nullptr);
+ auto nodeAddrInfoSync(const char *node, const char *service, addrinfo *hints = nullptr);
+@@ -153,7 +156,7 @@ class GetAddrInfoReq final: public Request<GetAddrInfoReq, uv_getaddrinfo_t> {
+ *
+ * To create a `GetNameInfoReq` through a `Loop`, no arguments are required.
+ */
+-class GetNameInfoReq final: public Request<GetNameInfoReq, uv_getnameinfo_t> {
++class UVW_EXTERN GetNameInfoReq final: public Request<GetNameInfoReq, uv_getnameinfo_t> {
+ static void nameInfoCallback(uv_getnameinfo_t *req, int status, const char *hostname, const char *service);
+
+ public:
+@@ -232,17 +235,17 @@ class GetNameInfoReq final: public Request<GetNameInfoReq, uv_getnameinfo_t> {
+
+ // (extern) explicit instantiations
+
+-extern template void GetNameInfoReq::nameInfo<IPv4>(std::string ip, unsigned int port, int flags);
+-extern template void GetNameInfoReq::nameInfo<IPv6>(std::string ip, unsigned int port, int flags);
++extern template UVW_EXTERN void GetNameInfoReq::nameInfo<IPv4>(std::string ip, unsigned int port, int flags);
++extern template UVW_EXTERN void GetNameInfoReq::nameInfo<IPv6>(std::string ip, unsigned int port, int flags);
+
+-extern template void GetNameInfoReq::nameInfo<IPv4>(Addr addr, int flags);
+-extern template void GetNameInfoReq::nameInfo<IPv6>(Addr addr, int flags);
++extern template UVW_EXTERN void GetNameInfoReq::nameInfo<IPv4>(Addr addr, int flags);
++extern template UVW_EXTERN void GetNameInfoReq::nameInfo<IPv6>(Addr addr, int flags);
+
+-extern template std::pair<bool, std::pair<const char *, const char *>> GetNameInfoReq::nameInfoSync<IPv4>(std::string ip, unsigned int port, int flags);
+-extern template std::pair<bool, std::pair<const char *, const char *>> GetNameInfoReq::nameInfoSync<IPv6>(std::string ip, unsigned int port, int flags);
++extern template UVW_EXTERN std::pair<bool, std::pair<const char *, const char *>> GetNameInfoReq::nameInfoSync<IPv4>(std::string ip, unsigned int port, int flags);
++extern template UVW_EXTERN std::pair<bool, std::pair<const char *, const char *>> GetNameInfoReq::nameInfoSync<IPv6>(std::string ip, unsigned int port, int flags);
+
+-extern template std::pair<bool, std::pair<const char *, const char *>> GetNameInfoReq::nameInfoSync<IPv4>(Addr addr, int flags);
+-extern template std::pair<bool, std::pair<const char *, const char *>> GetNameInfoReq::nameInfoSync<IPv6>(Addr addr, int flags);
++extern template UVW_EXTERN std::pair<bool, std::pair<const char *, const char *>> GetNameInfoReq::nameInfoSync<IPv4>(Addr addr, int flags);
++extern template UVW_EXTERN std::pair<bool, std::pair<const char *, const char *>> GetNameInfoReq::nameInfoSync<IPv6>(Addr addr, int flags);
+
+
+ }
+@@ -252,4 +255,6 @@ extern template std::pair<bool, std::pair<const char *, const char *>> GetNameIn
+ #include "dns.cpp"
+ #endif
+
++UVW_MSVC_WARNING_POP();
++
+ #endif // UVW_DNS_INCLUDE_H
+diff --git a/src/uvw/emitter.h b/src/uvw/emitter.h
+index a189f3a..c97e086 100644
+--- a/src/uvw/emitter.h
++++ b/src/uvw/emitter.h
+@@ -11,6 +11,9 @@
+ #include <memory>
+ #include <list>
+ #include <uv.h>
++#include "config.h"
++
++UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
+
+
+ namespace uvw {
+@@ -21,7 +24,7 @@ namespace uvw {
+ *
+ * Custom wrapper around error constants of `libuv`.
+ */
+-struct ErrorEvent {
++struct UVW_EXTERN ErrorEvent {
+ template<typename U, typename = std::enable_if_t<std::is_integral_v<U>>>
+ explicit ErrorEvent(U val) noexcept
+ : ec{static_cast<int>(val)}
+@@ -190,6 +193,14 @@ class Emitter {
+ }
+
+ public:
++ Emitter() = default;
++ Emitter(Emitter &&) = default;
++ Emitter & operator=(Emitter &&) = default;
++
++ // These must be deleted because MSVC try to export them with UVW_EXPORT
++ Emitter(const Emitter&) = delete;
++ Emitter& operator=(const Emitter&) = delete;
++
+ template<typename E>
+ using Listener = typename Handler<E>::Listener;
+
+@@ -321,4 +332,6 @@ class Emitter {
+ #include "emitter.cpp"
+ #endif
+
++UVW_MSVC_WARNING_POP();
++
+ #endif // UVW_EMITTER_INCLUDE_H
+diff --git a/src/uvw/fs.h b/src/uvw/fs.h
+index c4af1d4..d4a1ea1 100644
+--- a/src/uvw/fs.h
++++ b/src/uvw/fs.h
+@@ -10,6 +10,9 @@
+ #include "request.hpp"
+ #include "util.h"
+ #include "loop.h"
++#include "config.h"
++
++UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
+
+
+ namespace uvw {
+@@ -433,7 +436,7 @@ class FsRequest: public Request<T, uv_fs_t> {
+ * [documentation](http://docs.libuv.org/en/v1.x/fs.html)
+ * for further details.
+ */
+-class FileReq final: public FsRequest<FileReq> {
++class UVW_EXTERN FileReq final: public FsRequest<FileReq> {
+ static constexpr uv_file BAD_FD = -1;
+
+ static void fsOpenCallback(uv_fs_t *req);
+@@ -784,7 +787,7 @@ class FileReq final: public FsRequest<FileReq> {
+ * [documentation](http://docs.libuv.org/en/v1.x/fs.html)
+ * for further details.
+ */
+-class FsReq final: public FsRequest<FsReq> {
++class UVW_EXTERN FsReq final: public FsRequest<FsReq> {
+ static void fsReadlinkCallback(uv_fs_t *req);
+ static void fsReaddirCallback(uv_fs_t *req);
+
+@@ -1425,7 +1428,7 @@ class FsReq final: public FsRequest<FsReq> {
+
+
+ /*! @brief Helper functions. */
+-struct FsHelper {
++struct UVW_EXTERN FsHelper {
+ /**
+ * @brief Gets the OS dependent handle.
+ *
+@@ -1459,4 +1462,6 @@ struct FsHelper {
+ #include "fs.cpp"
+ #endif
+
++UVW_MSVC_WARNING_POP();
++
+ #endif // UVW_FS_INCLUDE_H
+diff --git a/src/uvw/fs_event.h b/src/uvw/fs_event.h
+index 6cbc5a0..ba15842 100644
+--- a/src/uvw/fs_event.h
++++ b/src/uvw/fs_event.h
+@@ -8,6 +8,9 @@
+ #include "handle.hpp"
+ #include "util.h"
+ #include "loop.h"
++#include "config.h"
++
++UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
+
+
+ namespace uvw {
+@@ -37,7 +40,7 @@ enum class UVFsEvent: std::underlying_type_t<uv_fs_event> {
+ *
+ * It will be emitted by FsEventHandle according with its functionalities.
+ */
+-struct FsEventEvent {
++struct UVW_EXTERN FsEventEvent {
+ FsEventEvent(const char * pathname, Flags<details::UVFsEvent> events);
+
+ /**
+@@ -58,6 +61,7 @@ struct FsEventEvent {
+ */
+ Flags<details::UVFsEvent> flags;
+ };
++template class UVW_EXTERN Flags<details::UVFsEvent>;
+
+
+ /**
+@@ -73,7 +77,7 @@ struct FsEventEvent {
+ * [documentation](http://docs.libuv.org/en/v1.x/fs_event.html)
+ * for further details.
+ */
+-class FsEventHandle final: public Handle<FsEventHandle, uv_fs_event_t> {
++class UVW_EXTERN FsEventHandle final: public Handle<FsEventHandle, uv_fs_event_t> {
+ static void startCallback(uv_fs_event_t *handle, const char *filename, int events, int status);
+
+ public:
+@@ -146,4 +150,6 @@ class FsEventHandle final: public Handle<FsEventHandle, uv_fs_event_t> {
+ #include "fs_event.cpp"
+ #endif
+
++UVW_MSVC_WARNING_POP();
++
+ #endif // UVW_FS_EVENT_INCLUDE_H
+diff --git a/src/uvw/fs_poll.h b/src/uvw/fs_poll.h
+index a264eb3..365669b 100644
+--- a/src/uvw/fs_poll.h
++++ b/src/uvw/fs_poll.h
+@@ -8,6 +8,9 @@
+ #include "handle.hpp"
+ #include "util.h"
+ #include "loop.h"
++#include "config.h"
++
++UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
+
+
+ namespace uvw {
+@@ -18,7 +21,7 @@ namespace uvw {
+ *
+ * It will be emitted by FsPollHandle according with its functionalities.
+ */
+-struct FsPollEvent {
++struct UVW_EXTERN FsPollEvent {
+ explicit FsPollEvent(Stat previous, Stat current) noexcept;
+
+ Stat prev; /*!< The old Stat struct. */
+@@ -35,7 +38,7 @@ struct FsPollEvent {
+ *
+ * To create a `FsPollHandle` through a `Loop`, no arguments are required.
+ */
+-class FsPollHandle final: public Handle<FsPollHandle, uv_fs_poll_t> {
++class UVW_EXTERN FsPollHandle final: public Handle<FsPollHandle, uv_fs_poll_t> {
+ static void startCallback(uv_fs_poll_t *handle, int status, const uv_stat_t *prev, const uv_stat_t *curr);
+
+ public:
+@@ -80,4 +83,6 @@ class FsPollHandle final: public Handle<FsPollHandle, uv_fs_poll_t> {
+ #include "fs_poll.cpp"
+ #endif
+
++UVW_MSVC_WARNING_POP();
++
+ #endif // UVW_FS_POLL_INCLUDE_H
+diff --git a/src/uvw/handle.hpp b/src/uvw/handle.hpp
+index 274f4fc..f459ff5 100644
+--- a/src/uvw/handle.hpp
++++ b/src/uvw/handle.hpp
+@@ -8,6 +8,9 @@
+ #include <uv.h>
+ #include "resource.hpp"
+ #include "util.h"
++#include "config.h"
++
++UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
+
+
+ namespace uvw {
+@@ -18,7 +21,7 @@ namespace uvw {
+ *
+ * It will be emitted by the handles according with their functionalities.
+ */
+-struct CloseEvent {};
++struct UVW_EXTERN CloseEvent {};
+
+
+ /**
+@@ -274,4 +277,6 @@ class Handle: public Resource<T, U>, public BaseHandle {
+
+ }
+
++UVW_MSVC_WARNING_POP();
++
+ #endif // UVW_HANDLE_INCLUDE_H
+diff --git a/src/uvw/idle.h b/src/uvw/idle.h
+index 28a8c12..af78ce1 100644
+--- a/src/uvw/idle.h
++++ b/src/uvw/idle.h
+@@ -5,6 +5,9 @@
+ #include <uv.h>
+ #include "handle.hpp"
+ #include "loop.h"
++#include "config.h"
++
++UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
+
+
+ namespace uvw {
+@@ -15,7 +18,7 @@ namespace uvw {
+ *
+ * It will be emitted by IdleHandle according with its functionalities.
+ */
+-struct IdleEvent {};
++struct UVW_EXTERN IdleEvent {};
+
+
+ /**
+@@ -34,7 +37,7 @@ struct IdleEvent {};
+ *
+ * To create an `IdleHandle` through a `Loop`, no arguments are required.
+ */
+-class IdleHandle final: public Handle<IdleHandle, uv_idle_t> {
++class UVW_EXTERN IdleHandle final: public Handle<IdleHandle, uv_idle_t> {
+ static void startCallback(uv_idle_t *handle);
+
+ public:
+@@ -68,4 +71,6 @@ class IdleHandle final: public Handle<IdleHandle, uv_idle_t> {
+ #include "idle.cpp"
+ #endif
+
++UVW_MSVC_WARNING_POP();
++
+ #endif // UVW_IDLE_INCLUDE_H
+diff --git a/src/uvw/lib.h b/src/uvw/lib.h
+index 7e8fff1..b8e293d 100644
+--- a/src/uvw/lib.h
++++ b/src/uvw/lib.h
+@@ -8,6 +8,9 @@
+ #include <uv.h>
+ #include "loop.h"
+ #include "underlying_type.hpp"
++#include "config.h"
++
++UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
+
+
+ namespace uvw {
+@@ -19,7 +22,7 @@ namespace uvw {
+ * `uvw` provides cross platform utilities for loading shared libraries and
+ * retrieving symbols from them, by means of the API offered by `libuv`.
+ */
+-class SharedLib final: public UnderlyingType<SharedLib, uv_lib_t> {
++class UVW_EXTERN SharedLib final: public UnderlyingType<SharedLib, uv_lib_t> {
+ public:
+ explicit SharedLib(ConstructorAccess ca, std::shared_ptr<Loop> ref, std::string filename) noexcept;
+
+@@ -67,4 +70,6 @@ class SharedLib final: public UnderlyingType<SharedLib, uv_lib_t> {
+ #include "lib.cpp"
+ #endif
+
++UVW_MSVC_WARNING_POP();
++
+ #endif // UVW_LIB_INCLUDE_H
+diff --git a/src/uvw/loop.h b/src/uvw/loop.h
+index 9832f0f..94c3a03 100644
+--- a/src/uvw/loop.h
++++ b/src/uvw/loop.h
+@@ -14,6 +14,9 @@
+ #include <uv.h>
+ #include "emitter.h"
+ #include "util.h"
++#include "config.h"
++
++UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
+
+
+ namespace uvw {
+@@ -45,7 +48,7 @@ enum class UVRunMode: std::underlying_type_t<uv_run_mode> {
+ * users walk them as untyped instances.<br/>
+ * This can help to end all the pending requests by closing the handles.
+ */
+-struct BaseHandle {
++struct UVW_EXTERN BaseHandle {
+ /**
+ * @brief Gets the category of the handle.
+ *
+@@ -140,7 +143,7 @@ struct BaseHandle {
+ * It takes care of polling for I/O and scheduling callbacks to be run based on
+ * different sources of events.
+ */
+-class Loop final: public Emitter<Loop>, public std::enable_shared_from_this<Loop> {
++class UVW_EXTERN Loop final: public Emitter<Loop>, public std::enable_shared_from_this<Loop> {
+ using Deleter = void(*)(uv_loop_t *);
+
+ template<typename, typename>
+@@ -425,9 +428,9 @@ class Loop final: public Emitter<Loop>, public std::enable_shared_from_this<Loop
+
+ // (extern) explicit instantiations
+
+-extern template bool Loop::run<Loop::Mode::DEFAULT>() noexcept;
+-extern template bool Loop::run<Loop::Mode::ONCE>() noexcept;
+-extern template bool Loop::run<Loop::Mode::NOWAIT>() noexcept;
++extern template UVW_EXTERN bool Loop::run<Loop::Mode::DEFAULT>() noexcept;
++extern template UVW_EXTERN bool Loop::run<Loop::Mode::ONCE>() noexcept;
++extern template UVW_EXTERN bool Loop::run<Loop::Mode::NOWAIT>() noexcept;
+
+
+ }
+@@ -437,4 +440,6 @@ extern template bool Loop::run<Loop::Mode::NOWAIT>() noexcept;
+ #include "loop.cpp"
+ #endif
+
++UVW_MSVC_WARNING_POP();
++
+ #endif // UVW_LOOP_INCLUDE_H
+diff --git a/src/uvw/pipe.h b/src/uvw/pipe.h
+index d37ea40..c71c9dc 100644
+--- a/src/uvw/pipe.h
++++ b/src/uvw/pipe.h
+@@ -10,6 +10,9 @@
+ #include "stream.h"
+ #include "util.h"
+ #include "loop.h"
++#include "config.h"
++
++UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
+
+
+ namespace uvw {
+@@ -38,7 +41,7 @@ enum class UVChmodFlags: std::underlying_type_t<uv_poll_event> {
+ * * An optional boolean value that indicates if this pipe will be used for
+ * handle passing between processes.
+ */
+-class PipeHandle final: public StreamHandle<PipeHandle, uv_pipe_t> {
++class UVW_EXTERN PipeHandle final: public StreamHandle<PipeHandle, uv_pipe_t> {
+ public:
+ using Chmod = details::UVChmodFlags;
+
+@@ -164,4 +167,6 @@ class PipeHandle final: public StreamHandle<PipeHandle, uv_pipe_t> {
+ #include "pipe.cpp"
+ #endif
+
++UVW_MSVC_WARNING_POP();
++
+ #endif // UVW_PIPE_INCLUDE_H
+diff --git a/src/uvw/poll.h b/src/uvw/poll.h
+index 6030fd5..f12a25f 100644
+--- a/src/uvw/poll.h
++++ b/src/uvw/poll.h
+@@ -7,6 +7,9 @@
+ #include <uv.h>
+ #include "handle.hpp"
+ #include "util.h"
++#include "config.h"
++
++UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
+
+
+ namespace uvw {
+@@ -31,7 +34,7 @@ enum class UVPollEvent: std::underlying_type_t<uv_poll_event> {
+ *
+ * It will be emitted by PollHandle according with its functionalities.
+ */
+-struct PollEvent {
++struct UVW_EXTERN PollEvent {
+ explicit PollEvent(Flags<details::UVPollEvent> events) noexcept;
+
+ /**
+@@ -46,6 +49,7 @@ struct PollEvent {
+ */
+ Flags<details::UVPollEvent> flags;
+ };
++template class UVW_EXTERN Flags<details::UVPollEvent>;
+
+
+ /**
+@@ -64,7 +68,7 @@ struct PollEvent {
+ * [documentation](http://docs.libuv.org/en/v1.x/poll.html)
+ * for further details.
+ */
+-class PollHandle final: public Handle<PollHandle, uv_poll_t> {
++class UVW_EXTERN PollHandle final: public Handle<PollHandle, uv_poll_t> {
+ static void startCallback(uv_poll_t *handle, int status, int events);
+
+ public:
+@@ -142,4 +146,6 @@ class PollHandle final: public Handle<PollHandle, uv_poll_t> {
+ #include "poll.cpp"
+ #endif
+
++UVW_MSVC_WARNING_POP();
++
+ #endif // UVW_POLL_INCLUDE_H
+diff --git a/src/uvw/prepare.h b/src/uvw/prepare.h
+index 736c7b8..9aab6e2 100644
+--- a/src/uvw/prepare.h
++++ b/src/uvw/prepare.h
+@@ -5,6 +5,9 @@
+ #include <uv.h>
+ #include "handle.hpp"
+ #include "loop.h"
++#include "config.h"
++
++UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
+
+
+ namespace uvw {
+@@ -15,7 +18,7 @@ namespace uvw {
+ *
+ * It will be emitted by PrepareHandle according with its functionalities.
+ */
+-struct PrepareEvent {};
++struct UVW_EXTERN PrepareEvent {};
+
+
+ /**
+@@ -26,7 +29,7 @@ struct PrepareEvent {};
+ *
+ * To create a `PrepareHandle` through a `Loop`, no arguments are required.
+ */
+-class PrepareHandle final: public Handle<PrepareHandle, uv_prepare_t> {
++class UVW_EXTERN PrepareHandle final: public Handle<PrepareHandle, uv_prepare_t> {
+ static void startCallback(uv_prepare_t *handle);
+
+ public:
+@@ -62,4 +65,6 @@ class PrepareHandle final: public Handle<PrepareHandle, uv_prepare_t> {
+ #include "prepare.cpp"
+ #endif
+
++UVW_MSVC_WARNING_POP();
++
+ #endif // UVW_PREPARE_INCLUDE_H
+diff --git a/src/uvw/process.h b/src/uvw/process.h
+index f19fcc4..378a934 100644
+--- a/src/uvw/process.h
++++ b/src/uvw/process.h
+@@ -11,6 +11,9 @@
+ #include "stream.h"
+ #include "util.h"
+ #include "loop.h"
++#include "config.h"
++
++UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
+
+
+ namespace uvw {
+@@ -49,7 +52,7 @@ enum class UVStdIOFlags: std::underlying_type_t<uv_stdio_flags> {
+ *
+ * It will be emitted by ProcessHandle according with its functionalities.
+ */
+-struct ExitEvent {
++struct UVW_EXTERN ExitEvent {
+ explicit ExitEvent(int64_t code, int sig) noexcept;
+
+ int64_t status; /*!< The exit status. */
+@@ -62,7 +65,7 @@ struct ExitEvent {
+ * Process handles will spawn a new process and allow the user to control it and
+ * establish communication channels with it using streams.
+ */
+-class ProcessHandle final: public Handle<ProcessHandle, uv_process_t> {
++class UVW_EXTERN ProcessHandle final: public Handle<ProcessHandle, uv_process_t> {
+ static void exitCallback(uv_process_t *handle, int64_t exitStatus, int termSignal);
+
+ public:
+@@ -242,6 +245,7 @@ class ProcessHandle final: public Handle<ProcessHandle, uv_process_t> {
+ Uid poUid;
+ Gid poGid;
+ };
++template class UVW_EXTERN Flags<ProcessHandle::Process>;
+
+
+ }
+@@ -251,4 +255,6 @@ class ProcessHandle final: public Handle<ProcessHandle, uv_process_t> {
+ #include "process.cpp"
+ #endif
+
++UVW_MSVC_WARNING_POP();
++
+ #endif // UVW_PROCESS_INCLUDE_H
+diff --git a/src/uvw/request.hpp b/src/uvw/request.hpp
+index 212ad39..2dd773d 100644
+--- a/src/uvw/request.hpp
++++ b/src/uvw/request.hpp
+@@ -7,6 +7,9 @@
+ #include <memory>
+ #include <uv.h>
+ #include "resource.hpp"
++#include "config.h"
++
++UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
+
+
+ namespace uvw {
+@@ -72,4 +75,6 @@ class Request: public Resource<T, U> {
+
+ }
+
++UVW_MSVC_WARNING_POP();
++
+ #endif // UVW_REQUEST_INCLUDE_H
+diff --git a/src/uvw/resource.hpp b/src/uvw/resource.hpp
+index 53c8adb..4f6d4ed 100644
+--- a/src/uvw/resource.hpp
++++ b/src/uvw/resource.hpp
+@@ -6,6 +6,9 @@
+ #include <utility>
+ #include "emitter.h"
+ #include "underlying_type.hpp"
++#include "config.h"
++
++UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
+
+
+ namespace uvw {
+@@ -70,4 +73,6 @@ class Resource: public UnderlyingType<T, U>, public Emitter<T>, public std::enab
+
+ }
+
++UVW_MSVC_WARNING_POP();
++
+ #endif // UVW_RESOURCE_INCLUDE_H
+diff --git a/src/uvw/signal.h b/src/uvw/signal.h
+index 93b6905..d357d14 100644
+--- a/src/uvw/signal.h
++++ b/src/uvw/signal.h
+@@ -5,6 +5,9 @@
+ #include <uv.h>
+ #include "handle.hpp"
+ #include "loop.h"
++#include "config.h"
++
++UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
+
+
+ namespace uvw {
+@@ -15,7 +18,7 @@ namespace uvw {
+ *
+ * It will be emitted by SignalHandle according with its functionalities.
+ */
+-struct SignalEvent {
++struct UVW_EXTERN SignalEvent {
+ explicit SignalEvent(int sig) noexcept;
+
+ int signum; /*!< The signal being monitored by this handle. */
+@@ -35,7 +38,7 @@ struct SignalEvent {
+ * [documentation](http://docs.libuv.org/en/v1.x/signal.html)
+ * for further details.
+ */
+-class SignalHandle final: public Handle<SignalHandle, uv_signal_t> {
++class UVW_EXTERN SignalHandle final: public Handle<SignalHandle, uv_signal_t> {
+ static void startCallback(uv_signal_t *handle, int signum);
+
+ public:
+@@ -86,4 +89,6 @@ class SignalHandle final: public Handle<SignalHandle, uv_signal_t> {
+ #include "signal.cpp"
+ #endif
+
++UVW_MSVC_WARNING_POP();
++
+ #endif // UVW_SIGNAL_INCLUDE_H
+diff --git a/src/uvw/stream.h b/src/uvw/stream.h
+index 88d6dc1..d8be7b0 100644
+--- a/src/uvw/stream.h
++++ b/src/uvw/stream.h
+@@ -11,6 +11,9 @@
+ #include "request.hpp"
+ #include "handle.hpp"
+ #include "loop.h"
++#include "config.h"
++
++UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
+
+
+ namespace uvw {
+@@ -21,7 +24,7 @@ namespace uvw {
+ *
+ * It will be emitted by StreamHandle according with its functionalities.
+ */
+-struct ConnectEvent {};
++struct UVW_EXTERN ConnectEvent {};
+
+
+ /**
+@@ -29,7 +32,7 @@ struct ConnectEvent {};
+ *
+ * It will be emitted by StreamHandle according with its functionalities.
+ */
+-struct EndEvent {};
++struct UVW_EXTERN EndEvent {};
+
+
+ /**
+@@ -37,7 +40,7 @@ struct EndEvent {};
+ *
+ * It will be emitted by StreamHandle according with its functionalities.
+ */
+-struct ListenEvent {};
++struct UVW_EXTERN ListenEvent {};
+
+
+ /**
+@@ -45,7 +48,7 @@ struct ListenEvent {};
+ *
+ * It will be emitted by StreamHandle according with its functionalities.
+ */
+-struct ShutdownEvent {};
++struct UVW_EXTERN ShutdownEvent {};
+
+
+ /**
+@@ -53,7 +56,7 @@ struct ShutdownEvent {};
+ *
+ * It will be emitted by StreamHandle according with its functionalities.
+ */
+-struct WriteEvent {};
++struct UVW_EXTERN WriteEvent {};
+
+
+ /**
+@@ -61,7 +64,7 @@ struct WriteEvent {};
+ *
+ * It will be emitted by StreamHandle according with its functionalities.
+ */
+-struct DataEvent {
++struct UVW_EXTERN DataEvent {
+ explicit DataEvent(std::unique_ptr<char[]> buf, std::size_t len) noexcept;
+
+ std::unique_ptr<char[]> data; /*!< A bunch of data read on the stream. */
+@@ -82,7 +85,7 @@ struct ConnectReq final: public Request<ConnectReq, uv_connect_t> {
+ };
+
+
+-struct ShutdownReq final: public Request<ShutdownReq, uv_shutdown_t> {
++struct UVW_EXTERN ShutdownReq final: public Request<ShutdownReq, uv_shutdown_t> {
+ using Request::Request;
+
+ void shutdown(uv_stream_t *handle);
+@@ -447,4 +450,6 @@ class StreamHandle: public Handle<T, U> {
+ #include "stream.cpp"
+ #endif
+
++UVW_MSVC_WARNING_POP();
++
+ #endif // UVW_STREAM_INCLUDE_H
+diff --git a/src/uvw/tcp.h b/src/uvw/tcp.h
+index 2b1e255..30b4a90 100644
+--- a/src/uvw/tcp.h
++++ b/src/uvw/tcp.h
+@@ -11,6 +11,9 @@
+ #include "request.hpp"
+ #include "stream.h"
+ #include "util.h"
++#include "config.h"
++
++UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
+
+
+ namespace uvw {
+@@ -43,7 +46,7 @@ enum class UVTCPFlags: std::underlying_type_t<uv_tcp_flags> {
+ * [documentation](http://docs.libuv.org/en/v1.x/tcp.html#c.uv_tcp_init_ex)
+ * for further details.
+ */
+-class TCPHandle final: public StreamHandle<TCPHandle, uv_tcp_t> {
++class UVW_EXTERN TCPHandle final: public StreamHandle<TCPHandle, uv_tcp_t> {
+ public:
+ using Time = std::chrono::duration<unsigned int>;
+ using Bind = details::UVTCPFlags;
+@@ -232,23 +235,23 @@ class TCPHandle final: public StreamHandle<TCPHandle, uv_tcp_t> {
+
+ // (extern) explicit instantiations
+
+-extern template void TCPHandle::bind<IPv4>(std::string, unsigned int, Flags<Bind>);
+-extern template void TCPHandle::bind<IPv6>(std::string, unsigned int, Flags<Bind>);
++extern template UVW_EXTERN void TCPHandle::bind<IPv4>(std::string, unsigned int, Flags<Bind>);
++extern template UVW_EXTERN void TCPHandle::bind<IPv6>(std::string, unsigned int, Flags<Bind>);
+
+-extern template void TCPHandle::bind<IPv4>(Addr, Flags<Bind>);
+-extern template void TCPHandle::bind<IPv6>(Addr, Flags<Bind>);
++extern template UVW_EXTERN void TCPHandle::bind<IPv4>(Addr, Flags<Bind>);
++extern template UVW_EXTERN void TCPHandle::bind<IPv6>(Addr, Flags<Bind>);
+
+-extern template Addr TCPHandle::sock<IPv4>() const noexcept;
+-extern template Addr TCPHandle::sock<IPv6>() const noexcept;
++extern template UVW_EXTERN Addr TCPHandle::sock<IPv4>() const noexcept;
++extern template UVW_EXTERN Addr TCPHandle::sock<IPv6>() const noexcept;
+
+-extern template Addr TCPHandle::peer<IPv4>() const noexcept;
+-extern template Addr TCPHandle::peer<IPv6>() const noexcept;
++extern template UVW_EXTERN Addr TCPHandle::peer<IPv4>() const noexcept;
++extern template UVW_EXTERN Addr TCPHandle::peer<IPv6>() const noexcept;
+
+-extern template void TCPHandle::connect<IPv4>(std::string, unsigned int);
+-extern template void TCPHandle::connect<IPv6>(std::string, unsigned int);
++extern template UVW_EXTERN void TCPHandle::connect<IPv4>(std::string, unsigned int);
++extern template UVW_EXTERN void TCPHandle::connect<IPv6>(std::string, unsigned int);
+
+-extern template void TCPHandle::connect<IPv4>(Addr addr);
+-extern template void TCPHandle::connect<IPv6>(Addr addr);
++extern template UVW_EXTERN void TCPHandle::connect<IPv4>(Addr addr);
++extern template UVW_EXTERN void TCPHandle::connect<IPv6>(Addr addr);
+
+
+ }
+@@ -258,4 +261,6 @@ extern template void TCPHandle::connect<IPv6>(Addr addr);
+ #include "tcp.cpp"
+ #endif
+
++UVW_MSVC_WARNING_POP();
++
+ #endif // UVW_TCP_INCLUDE_H
+diff --git a/src/uvw/thread.h b/src/uvw/thread.h
+index 912d8a1..07481d3 100644
+--- a/src/uvw/thread.h
++++ b/src/uvw/thread.h
+@@ -10,6 +10,9 @@
+ #include <uv.h>
+ #include "loop.h"
+ #include "underlying_type.hpp"
++#include "config.h"
++
++UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
+
+
+ namespace uvw {
+@@ -46,7 +49,7 @@ class Barrier;
+ * that it can be assigned to an `std::function<void(std::shared_ptr<void>)>`.
+ * * An optional payload the type of which is `std::shared_ptr<void>`.
+ */
+-class Thread final: public UnderlyingType<Thread, uv_thread_t> {
++class UVW_EXTERN Thread final: public UnderlyingType<Thread, uv_thread_t> {
+ using InternalTask = std::function<void(std::shared_ptr<void>)>;
+
+ static void createCallback(void *arg);
+@@ -114,7 +117,7 @@ class Thread final: public UnderlyingType<Thread, uv_thread_t> {
+ * seen as a global variable that is only visible to a particular thread and not
+ * the whole program.
+ */
+-class ThreadLocalStorage final: public UnderlyingType<ThreadLocalStorage, uv_key_t> {
++class UVW_EXTERN ThreadLocalStorage final: public UnderlyingType<ThreadLocalStorage, uv_key_t> {
+ public:
+ explicit ThreadLocalStorage(ConstructorAccess ca, std::shared_ptr<Loop> ref) noexcept;
+
+@@ -148,7 +151,7 @@ class ThreadLocalStorage final: public UnderlyingType<ThreadLocalStorage, uv_key
+ * Runs a function once and only once. Concurrent calls to `once` will block all
+ * callers except one (it’s unspecified which one).
+ */
+-class Once final: public UnderlyingType<Once, uv_once_t> {
++class UVW_EXTERN Once final: public UnderlyingType<Once, uv_once_t> {
+ static uv_once_t* guard() noexcept;
+
+ public:
+@@ -181,7 +184,7 @@ class Once final: public UnderlyingType<Once, uv_once_t> {
+ * * An option boolean that specifies if the mutex is a recursive one. The
+ * default value is false, the mutex isn't recursive.
+ */
+-class Mutex final: public UnderlyingType<Mutex, uv_mutex_t> {
++class UVW_EXTERN Mutex final: public UnderlyingType<Mutex, uv_mutex_t> {
+ friend class Condition;
+
+ public:
+@@ -210,7 +213,7 @@ class Mutex final: public UnderlyingType<Mutex, uv_mutex_t> {
+ /**
+ * @brief The RWLock wrapper.
+ */
+-class RWLock final: public UnderlyingType<RWLock, uv_rwlock_t> {
++class UVW_EXTERN RWLock final: public UnderlyingType<RWLock, uv_rwlock_t> {
+ public:
+ explicit RWLock(ConstructorAccess ca, std::shared_ptr<Loop> ref) noexcept;
+
+@@ -257,7 +260,7 @@ class RWLock final: public UnderlyingType<RWLock, uv_rwlock_t> {
+ *
+ * * An unsigned integer that specifies the initial value for the semaphore.
+ */
+-class Semaphore final: public UnderlyingType<Semaphore, uv_sem_t> {
++class UVW_EXTERN Semaphore final: public UnderlyingType<Semaphore, uv_sem_t> {
+ public:
+ explicit Semaphore(ConstructorAccess ca, std::shared_ptr<Loop> ref, unsigned int value) noexcept;
+
+@@ -284,7 +287,7 @@ class Semaphore final: public UnderlyingType<Semaphore, uv_sem_t> {
+ /**
+ * @brief The Condition wrapper.
+ */
+-class Condition final: public UnderlyingType<Condition, uv_cond_t> {
++class UVW_EXTERN Condition final: public UnderlyingType<Condition, uv_cond_t> {
+ public:
+ explicit Condition(ConstructorAccess ca, std::shared_ptr<Loop> ref) noexcept;
+
+@@ -344,7 +347,7 @@ class Condition final: public UnderlyingType<Condition, uv_cond_t> {
+ * `wait` before any of them successfully return from the call. The value
+ * specified must be greater than zero.
+ */
+-class Barrier final: public UnderlyingType<Barrier, uv_barrier_t> {
++class UVW_EXTERN Barrier final: public UnderlyingType<Barrier, uv_barrier_t> {
+ public:
+ explicit Barrier(ConstructorAccess ca, std::shared_ptr<Loop> ref, unsigned int count) noexcept;
+
+@@ -365,4 +368,6 @@ class Barrier final: public UnderlyingType<Barrier, uv_barrier_t> {
+ #include "thread.cpp"
+ #endif
+
++UVW_MSVC_WARNING_POP();
++
+ #endif // UVW_THREAD_INCLUDE_H
+diff --git a/src/uvw/timer.h b/src/uvw/timer.h
+index b1fbb43..443de0e 100644
+--- a/src/uvw/timer.h
++++ b/src/uvw/timer.h
+@@ -6,6 +6,9 @@
+ #include <uv.h>
+ #include "handle.hpp"
+ #include "loop.h"
++#include "config.h"
++
++UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
+
+
+ namespace uvw {
+@@ -16,7 +19,7 @@ namespace uvw {
+ *
+ * It will be emitted by TimerHandle according with its functionalities.
+ */
+-struct TimerEvent {};
++struct UVW_EXTERN TimerEvent {};
+
+
+ /**
+@@ -26,7 +29,7 @@ struct TimerEvent {};
+ *
+ * To create a `TimerHandle` through a `Loop`, no arguments are required.
+ */
+-class TimerHandle final: public Handle<TimerHandle, uv_timer_t> {
++class UVW_EXTERN TimerHandle final: public Handle<TimerHandle, uv_timer_t> {
+ static void startCallback(uv_timer_t *handle);
+
+ public:
+@@ -104,4 +107,6 @@ class TimerHandle final: public Handle<TimerHandle, uv_timer_t> {
+ #include "timer.cpp"
+ #endif
+
++UVW_MSVC_WARNING_POP();
++
+ #endif // UVW_TIMER_INCLUDE_H
+diff --git a/src/uvw/tty.h b/src/uvw/tty.h
+index bbfb1ff..9b283cd 100644
+--- a/src/uvw/tty.h
++++ b/src/uvw/tty.h
+@@ -7,6 +7,9 @@
+ #include <uv.h>
+ #include "stream.h"
+ #include "util.h"
++#include "config.h"
++
++UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
+
+
+ namespace uvw {
+@@ -15,7 +18,7 @@ namespace uvw {
+ namespace details {
+
+
+-struct ResetModeMemo {
++struct UVW_EXTERN ResetModeMemo {
+ ~ResetModeMemo();
+ };
+
+@@ -54,7 +57,7 @@ enum class UVTTYVTermStateT: std::underlying_type_t<uv_tty_vtermstate_t> {
+ * [documentation](http://docs.libuv.org/en/v1.x/tty.html#c.uv_tty_init)
+ * for further details.
+ */
+-class TTYHandle final: public StreamHandle<TTYHandle, uv_tty_t> {
++class UVW_EXTERN TTYHandle final: public StreamHandle<TTYHandle, uv_tty_t> {
+ static std::shared_ptr<details::ResetModeMemo> resetModeMemo();
+
+ public:
+@@ -152,4 +155,6 @@ class TTYHandle final: public StreamHandle<TTYHandle, uv_tty_t> {
+ #include "tty.cpp"
+ #endif
+
++UVW_MSVC_WARNING_POP();
++
+ #endif // UVW_TTY_INCLUDE_H
+diff --git a/src/uvw/udp.h b/src/uvw/udp.h
+index 68769a8..3251b02 100644
+--- a/src/uvw/udp.h
++++ b/src/uvw/udp.h
+@@ -11,6 +11,9 @@
+ #include "request.hpp"
+ #include "handle.hpp"
+ #include "util.h"
++#include "config.h"
++
++UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
+
+
+ namespace uvw {
+@@ -21,7 +24,7 @@ namespace uvw {
+ *
+ * It will be emitted by UDPHandle according with its functionalities.
+ */
+-struct SendEvent {};
++struct UVW_EXTERN SendEvent {};
+
+
+ /**
+@@ -29,7 +32,7 @@ struct SendEvent {};
+ *
+ * It will be emitted by UDPHandle according with its functionalities.
+ */
+-struct UDPDataEvent {
++struct UVW_EXTERN UDPDataEvent {
+ explicit UDPDataEvent(Addr sndr, std::unique_ptr<const char[]> buf, std::size_t len, bool part) noexcept;
+
+ std::unique_ptr<const char[]> data; /*!< A bunch of data read on the stream. */
+@@ -57,7 +60,7 @@ enum class UVMembership: std::underlying_type_t<uv_membership> {
+ };
+
+
+-class SendReq final: public Request<SendReq, uv_udp_send_t> {
++class UVW_EXTERN SendReq final: public Request<SendReq, uv_udp_send_t> {
+ public:
+ using Deleter = void(*)(char *);
+
+@@ -90,7 +93,7 @@ class SendReq final: public Request<SendReq, uv_udp_send_t> {
+ * [documentation](http://docs.libuv.org/en/v1.x/udp.html#c.uv_udp_init_ex)
+ * for further details.
+ */
+-class UDPHandle final: public Handle<UDPHandle, uv_udp_t> {
++class UVW_EXTERN UDPHandle final: public Handle<UDPHandle, uv_udp_t> {
+ template<typename I>
+ static void recvCallback(uv_udp_t *handle, ssize_t nread, const uv_buf_t *buf, const sockaddr *addr, unsigned flags) {
+ const typename details::IpTraits<I>::Type *aptr = reinterpret_cast<const typename details::IpTraits<I>::Type *>(addr);
+@@ -578,62 +581,62 @@ class UDPHandle final: public Handle<UDPHandle, uv_udp_t> {
+
+ // (extern) explicit instantiations
+
+-extern template void UDPHandle::connect<IPv4>(std::string, unsigned int);
+-extern template void UDPHandle::connect<IPv6>(std::string, unsigned int);
++extern template UVW_EXTERN void UDPHandle::connect<IPv4>(std::string, unsigned int);
++extern template UVW_EXTERN void UDPHandle::connect<IPv6>(std::string, unsigned int);
+
+-extern template void UDPHandle::connect<IPv4>(Addr);
+-extern template void UDPHandle::connect<IPv6>(Addr);
++extern template UVW_EXTERN void UDPHandle::connect<IPv4>(Addr);
++extern template UVW_EXTERN void UDPHandle::connect<IPv6>(Addr);
+
+-extern template Addr UDPHandle::peer<IPv4>() const noexcept;
+-extern template Addr UDPHandle::peer<IPv6>() const noexcept;
++extern template UVW_EXTERN Addr UDPHandle::peer<IPv4>() const noexcept;
++extern template UVW_EXTERN Addr UDPHandle::peer<IPv6>() const noexcept;
+
+-extern template void UDPHandle::bind<IPv4>(std::string, unsigned int, Flags<Bind>);
+-extern template void UDPHandle::bind<IPv6>(std::string, unsigned int, Flags<Bind>);
++extern template UVW_EXTERN void UDPHandle::bind<IPv4>(std::string, unsigned int, Flags<Bind>);
++extern template UVW_EXTERN void UDPHandle::bind<IPv6>(std::string, unsigned int, Flags<Bind>);
+
+-extern template void UDPHandle::bind<IPv4>(Addr, Flags<Bind>);
+-extern template void UDPHandle::bind<IPv6>(Addr, Flags<Bind>);
++extern template UVW_EXTERN void UDPHandle::bind<IPv4>(Addr, Flags<Bind>);
++extern template UVW_EXTERN void UDPHandle::bind<IPv6>(Addr, Flags<Bind>);
+
+-extern template Addr UDPHandle::sock<IPv4>() const noexcept;
+-extern template Addr UDPHandle::sock<IPv6>() const noexcept;
++extern template UVW_EXTERN Addr UDPHandle::sock<IPv4>() const noexcept;
++extern template UVW_EXTERN Addr UDPHandle::sock<IPv6>() const noexcept;
+
+-extern template bool UDPHandle::multicastMembership<IPv4>(std::string, std::string, Membership);
+-extern template bool UDPHandle::multicastMembership<IPv6>(std::string, std::string, Membership);
++extern template UVW_EXTERN bool UDPHandle::multicastMembership<IPv4>(std::string, std::string, Membership);
++extern template UVW_EXTERN bool UDPHandle::multicastMembership<IPv6>(std::string, std::string, Membership);
+
+-extern template bool UDPHandle::multicastInterface<IPv4>(std::string);
+-extern template bool UDPHandle::multicastInterface<IPv6>(std::string);
++extern template UVW_EXTERN bool UDPHandle::multicastInterface<IPv4>(std::string);
++extern template UVW_EXTERN bool UDPHandle::multicastInterface<IPv6>(std::string);
+
+-extern template void UDPHandle::send<IPv4>(std::string, unsigned int, std::unique_ptr<char[]>, unsigned int);
+-extern template void UDPHandle::send<IPv6>(std::string, unsigned int, std::unique_ptr<char[]>, unsigned int);
++extern template UVW_EXTERN void UDPHandle::send<IPv4>(std::string, unsigned int, std::unique_ptr<char[]>, unsigned int);
++extern template UVW_EXTERN void UDPHandle::send<IPv6>(std::string, unsigned int, std::unique_ptr<char[]>, unsigned int);
+
+-extern template void UDPHandle::send<IPv4>(Addr, std::unique_ptr<char[]>, unsigned int);
+-extern template void UDPHandle::send<IPv6>(Addr, std::unique_ptr<char[]>, unsigned int);
++extern template UVW_EXTERN void UDPHandle::send<IPv4>(Addr, std::unique_ptr<char[]>, unsigned int);
++extern template UVW_EXTERN void UDPHandle::send<IPv6>(Addr, std::unique_ptr<char[]>, unsigned int);
+
+-extern template void UDPHandle::send<IPv4>(std::string, unsigned int, char *, unsigned int);
+-extern template void UDPHandle::send<IPv6>(std::string, unsigned int, char *, unsigned int);
++extern template UVW_EXTERN void UDPHandle::send<IPv4>(std::string, unsigned int, char *, unsigned int);
++extern template UVW_EXTERN void UDPHandle::send<IPv6>(std::string, unsigned int, char *, unsigned int);
+
+-extern template void UDPHandle::send<IPv4>(Addr, char *, unsigned int);
+-extern template void UDPHandle::send<IPv6>(Addr, char *, unsigned int);
++extern template UVW_EXTERN void UDPHandle::send<IPv4>(Addr, char *, unsigned int);
++extern template UVW_EXTERN void UDPHandle::send<IPv6>(Addr, char *, unsigned int);
+
+-extern template int UDPHandle::trySend<IPv4>(const sockaddr &, std::unique_ptr<char[]>, unsigned int);
+-extern template int UDPHandle::trySend<IPv6>(const sockaddr &, std::unique_ptr<char[]>, unsigned int);
++extern template UVW_EXTERN int UDPHandle::trySend<IPv4>(const sockaddr &, std::unique_ptr<char[]>, unsigned int);
++extern template UVW_EXTERN int UDPHandle::trySend<IPv6>(const sockaddr &, std::unique_ptr<char[]>, unsigned int);
+
+-extern template int UDPHandle::trySend<IPv4>(std::string, unsigned int, std::unique_ptr<char[]>, unsigned int);
+-extern template int UDPHandle::trySend<IPv6>(std::string, unsigned int, std::unique_ptr<char[]>, unsigned int);
++extern template UVW_EXTERN int UDPHandle::trySend<IPv4>(std::string, unsigned int, std::unique_ptr<char[]>, unsigned int);
++extern template UVW_EXTERN int UDPHandle::trySend<IPv6>(std::string, unsigned int, std::unique_ptr<char[]>, unsigned int);
+
+-extern template int UDPHandle::trySend<IPv4>(Addr, std::unique_ptr<char[]>, unsigned int);
+-extern template int UDPHandle::trySend<IPv6>(Addr, std::unique_ptr<char[]>, unsigned int);
++extern template UVW_EXTERN int UDPHandle::trySend<IPv4>(Addr, std::unique_ptr<char[]>, unsigned int);
++extern template UVW_EXTERN int UDPHandle::trySend<IPv6>(Addr, std::unique_ptr<char[]>, unsigned int);
+
+-extern template int UDPHandle::trySend<IPv4>(const sockaddr &, char *, unsigned int);
+-extern template int UDPHandle::trySend<IPv6>(const sockaddr &, char *, unsigned int);
++extern template UVW_EXTERN int UDPHandle::trySend<IPv4>(const sockaddr &, char *, unsigned int);
++extern template UVW_EXTERN int UDPHandle::trySend<IPv6>(const sockaddr &, char *, unsigned int);
+
+-extern template int UDPHandle::trySend<IPv4>(std::string, unsigned int, char *, unsigned int);
+-extern template int UDPHandle::trySend<IPv6>(std::string, unsigned int, char *, unsigned int);
++extern template UVW_EXTERN int UDPHandle::trySend<IPv4>(std::string, unsigned int, char *, unsigned int);
++extern template UVW_EXTERN int UDPHandle::trySend<IPv6>(std::string, unsigned int, char *, unsigned int);
+
+-extern template int UDPHandle::trySend<IPv4>(Addr, char *, unsigned int);
+-extern template int UDPHandle::trySend<IPv6>(Addr, char *, unsigned int);
++extern template UVW_EXTERN int UDPHandle::trySend<IPv4>(Addr, char *, unsigned int);
++extern template UVW_EXTERN int UDPHandle::trySend<IPv6>(Addr, char *, unsigned int);
+
+-extern template void UDPHandle::recv<IPv4>();
+-extern template void UDPHandle::recv<IPv6>();
++extern template UVW_EXTERN void UDPHandle::recv<IPv4>();
++extern template UVW_EXTERN void UDPHandle::recv<IPv6>();
+
+ }
+
+@@ -642,4 +645,6 @@ extern template void UDPHandle::recv<IPv6>();
+ #include "udp.cpp"
+ #endif
+
++UVW_MSVC_WARNING_POP();
++
+ #endif // UVW_UDP_INCLUDE_H
+diff --git a/src/uvw/underlying_type.hpp b/src/uvw/underlying_type.hpp
+index 06c4a57..78cd5d7 100644
+--- a/src/uvw/underlying_type.hpp
++++ b/src/uvw/underlying_type.hpp
+@@ -6,6 +6,9 @@
+ #include <type_traits>
+ #include <utility>
+ #include "loop.h"
++#include "config.h"
++
++UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
+
+
+ namespace uvw {
+@@ -116,4 +119,6 @@ class UnderlyingType {
+
+ }
+
++UVW_MSVC_WARNING_POP();
++
+ #endif // UVW_UNDERLYING_TYPE_INCLUDE_H
+diff --git a/src/uvw/util.cpp b/src/uvw/util.cpp
+index 95ef325..2f8a3a2 100644
+--- a/src/uvw/util.cpp
++++ b/src/uvw/util.cpp
+@@ -69,6 +69,10 @@ UVW_INLINE std::string UtsName::machine() const noexcept {
+ return utsname ? utsname->machine : "";
+ }
+
++const details::IpTraits<IPv4>::AddrFuncType details::IpTraits<IPv4>::addrFunc = &uv_ip4_addr;
++const details::IpTraits<IPv4>::NameFuncType details::IpTraits<IPv4>::nameFunc = &uv_ip4_name;
++const details::IpTraits<IPv6>::AddrFuncType details::IpTraits<IPv6>::addrFunc = &uv_ip6_addr;
++const details::IpTraits<IPv6>::NameFuncType details::IpTraits<IPv6>::nameFunc = &uv_ip6_name;
+
+ UVW_INLINE PidType Utilities::OS::pid() noexcept {
+ return uv_os_getpid();
+diff --git a/src/uvw/util.h b/src/uvw/util.h
+index 4227137..93c7b34 100644
+--- a/src/uvw/util.h
++++ b/src/uvw/util.h
+@@ -11,6 +11,9 @@
+ #include <memory>
+ #include <array>
+ #include <uv.h>
++#include "config.h"
++
++UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
+
+
+ namespace uvw {
+@@ -177,7 +180,7 @@ class Flags final {
+ /**
+ * @brief Windows size representation.
+ */
+-struct WinSize {
++struct UVW_EXTERN WinSize {
+ int width; /*!< The _width_ of the given window. */
+ int height; /*!< The _height_ of the given window. */
+ };
+@@ -214,7 +217,7 @@ using RUsage = uv_rusage_t; /*!< Library equivalent for uv_rusage_t. */
+ *
+ * \sa Utilities::passwd
+ */
+-struct Passwd {
++struct UVW_EXTERN Passwd {
+ Passwd(std::shared_ptr<uv_passwd_t> pwd);
+
+ /**
+@@ -267,7 +270,7 @@ struct Passwd {
+ *
+ * \sa Utilities::uname
+ */
+-struct UtsName {
++struct UVW_EXTERN UtsName {
+ UtsName(std::shared_ptr<uv_utsname_t> utsname);
+
+ /**
+@@ -304,7 +307,7 @@ struct UtsName {
+ *
+ * To be used as template parameter to switch between IPv4 and IPv6.
+ */
+-struct IPv4 {};
++struct UVW_EXTERN IPv4 {};
+
+
+ /**
+@@ -312,13 +315,13 @@ struct IPv4 {};
+ *
+ * To be used as template parameter to switch between IPv4 and IPv6.
+ */
+-struct IPv6 {};
++struct UVW_EXTERN IPv6 {};
+
+
+ /**
+ * @brief Address representation.
+ */
+-struct Addr {
++struct UVW_EXTERN Addr {
+ std::string ip; /*!< Either an IPv4 or an IPv6. */
+ unsigned int port; /*!< A valid service identifier. */
+ };
+@@ -327,7 +330,7 @@ struct Addr {
+ /**
+ * \brief CPU information.
+ */
+-struct CPUInfo {
++struct UVW_EXTERN CPUInfo {
+ using CPUTime = decltype(uv_cpu_info_t::cpu_times);
+
+ std::string model; /*!< The model of the CPU. */
+@@ -346,7 +349,7 @@ struct CPUInfo {
+ /**
+ * \brief Interface address.
+ */
+-struct InterfaceAddress {
++struct UVW_EXTERN InterfaceAddress {
+ std::string name; /*!< The name of the interface (as an example _eth0_). */
+ char physical[6]; /*!< The physical address. */
+ bool internal; /*!< True if it is an internal interface (as an example _loopback_), false otherwise. */
+@@ -364,14 +367,13 @@ static constexpr std::size_t DEFAULT_SIZE = 128;
+ template<typename>
+ struct IpTraits;
+
+-
+ template<>
+ struct IpTraits<IPv4> {
+ using Type = sockaddr_in;
+- using AddrFuncType = int(*)(const char *, int, Type *);
+- using NameFuncType = int(*)(const Type *, char *, std::size_t);
+- static constexpr AddrFuncType addrFunc = &uv_ip4_addr;
+- static constexpr NameFuncType nameFunc = &uv_ip4_name;
++ using AddrFuncType = int (*)(const char*, int, Type*);
++ using NameFuncType = int (*)(const Type*, char*, std::size_t);
++ static UVW_EXTERN const AddrFuncType addrFunc;
++ static UVW_EXTERN const NameFuncType nameFunc;
+ static constexpr auto sinPort(const Type *addr) { return addr->sin_port; }
+ };
+
+@@ -381,8 +383,8 @@ struct IpTraits<IPv6> {
+ using Type = sockaddr_in6;
+ using AddrFuncType = int(*)(const char *, int, Type *);
+ using NameFuncType = int(*)(const Type *, char *, std::size_t);
+- static constexpr AddrFuncType addrFunc = &uv_ip6_addr;
+- static constexpr NameFuncType nameFunc = &uv_ip6_name;
++ static UVW_EXTERN const AddrFuncType addrFunc;
++ static UVW_EXTERN const NameFuncType nameFunc;
+ static constexpr auto sinPort(const Type *addr) { return addr->sin6_port; }
+ };
+
+@@ -450,7 +452,7 @@ std::string tryRead(F &&f, Args&&... args) noexcept {
+ *
+ * Miscellaneous functions that don’t really belong to any other class.
+ */
+-struct Utilities {
++struct UVW_EXTERN Utilities {
+ using MallocFuncType = void*(*)(size_t);
+ using ReallocFuncType = void*(*)(void*, size_t);
+ using CallocFuncType = void*(*)(size_t, size_t);
+@@ -459,7 +461,7 @@ struct Utilities {
+ /**
+ * @brief OS dedicated utilities.
+ */
+- struct OS {
++ struct UVW_EXTERN OS {
+ /**
+ * @brief Returns the current process id.
+ *
+@@ -829,4 +831,6 @@ struct Utilities {
+ #include "util.cpp"
+ #endif
+
++UVW_MSVC_WARNING_POP();
++
+ #endif // UVW_UTIL_INCLUDE_H
+diff --git a/src/uvw/work.h b/src/uvw/work.h
+index 00cc86f..f5b9c3c 100644
+--- a/src/uvw/work.h
++++ b/src/uvw/work.h
+@@ -7,6 +7,9 @@
+ #include <uv.h>
+ #include "request.hpp"
+ #include "loop.h"
++#include "config.h"
++
++UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
+
+
+ namespace uvw {
+@@ -17,7 +20,7 @@ namespace uvw {
+ *
+ * It will be emitted by WorkReq according with its functionalities.
+ */
+-struct WorkEvent {};
++struct UVW_EXTERN WorkEvent {};
+
+
+ /**
+@@ -34,7 +37,7 @@ struct WorkEvent {};
+ * [documentation](http://docs.libuv.org/en/v1.x/threadpool.html)
+ * for further details.
+ */
+-class WorkReq final: public Request<WorkReq, uv_work_t> {
++class UVW_EXTERN WorkReq final: public Request<WorkReq, uv_work_t> {
+ using InternalTask = std::function<void(void)>;
+
+ static void workCallback(uv_work_t *req);
+@@ -65,4 +68,6 @@ class WorkReq final: public Request<WorkReq, uv_work_t> {
+ #include "work.cpp"
+ #endif
+
++UVW_MSVC_WARNING_POP();
++
+ #endif // UVW_WORK_INCLUDE_H
+diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
+index 8d0b3e7..672eb4b 100644
+--- a/test/CMakeLists.txt
++++ b/test/CMakeLists.txt
+@@ -46,8 +46,8 @@ function(ADD_UVW_TEST TEST_NAME TEST_SOURCE)
+ ${TEST_NAME}
+ PRIVATE
+ $<$<TARGET_EXISTS:uvw::uvw>:uvw::uvw>
+- $<$<TARGET_EXISTS:uvw::uvw>:uv::uv-static>
+- $<$<TARGET_EXISTS:uvw::uvw-static>:uvw::uvw-static>
++ $<$<TARGET_EXISTS:uv::uv-shared>:uv::uv-shared>
++ $<$<TARGET_EXISTS:uvw::uvw-shared>:uvw::uvw-shared>
+ GTest::Main
+ Threads::Threads
+ ${LIBRT}
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 25e6c12..ea1700a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -29,6 +29,7 @@ function(add_uvw_library LIB_NAME)
uvw/udp.cpp
uvw/util.cpp
uvw/work.cpp
+ uvw/type_factory/type_factory.cpp
)
set_target_properties(${LIB_NAME} PROPERTIES POSITION_INDEPENDENT_CODE 1)
@@ -74,8 +75,20 @@ add_uvw_library(uvw-static)
add_library(uvw-shared SHARED)
add_library(uvw::uvw-shared ALIAS uvw-shared)
target_link_libraries(uvw-shared PUBLIC uv::uv-shared)
-set_target_properties(uvw-shared PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${UVW_VERSION_MAJOR} EXCLUDE_FROM_DEFAULT_BUILD 1)
+set_target_properties(uvw-shared PROPERTIES
+ VERSION ${PROJECT_VERSION}
+ SOVERSION ${UVW_VERSION_MAJOR}
+ EXCLUDE_FROM_DEFAULT_BUILD 1
+ C_VISIBILITY_PRESET hidden
+ CXX_VISIBILITY_PRESET hidden
+)
add_uvw_library(uvw-shared)
+target_compile_definitions(uvw-shared
+ INTERFACE
+ USING_UVW_SHARED=1
+ PRIVATE
+ BUILDING_UVW_SHARED=1
+)
#
# Install targets
diff --git a/src/uvw.hpp b/src/uvw.hpp
index aaf8f4c..c4ba5cf 100644
--- a/src/uvw.hpp
+++ b/src/uvw.hpp
@@ -25,3 +25,244 @@
#include "uvw/underlying_type.hpp"
#include "uvw/util.h"
#include "uvw/work.h"
+
+namespace uvw {
+ extern template UVW_EXTERN std::size_t details::type_factory<IdleHandle>::event_type<ErrorEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<IdleHandle>::event_type<CloseEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<IdleHandle>::event_type<IdleEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<AsyncHandle>::event_type<AsyncEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<AsyncHandle>::event_type<ErrorEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<WorkReq>::event_type<WorkEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 1> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 2> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 3> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 4> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 5> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 6> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 7> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 8> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 9> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 10> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 11> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 12> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 13> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 14> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 15> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 16> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 17> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 18> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 19> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 20> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 21> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 22> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 23> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 24> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 25> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 26> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 27> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 28> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 29> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 30> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 31> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 32> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 33> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 34> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 35> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 36> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 37> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 38> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 39> >() noexcept;
+
+
+ extern template UVW_EXTERN std::size_t details::type_factory<details::ShutdownReq>::event_type<ErrorEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FileReq>::event_type<FsEvent<(details::UVFsType) 11> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<GetNameInfoReq>::event_type<NameInfoEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<TimerHandle>::event_type<TimerEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<CheckHandle>::event_type<ErrorEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsReq>::event_type<ErrorEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FileReq>::event_type<FsEvent<(details::UVFsType) 27> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<details::SendReq>::event_type<ErrorEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FileReq>::event_type<FsEvent<(details::UVFsType) 9> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<TCPHandle>::event_type<CloseEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<ProcessHandle>::event_type<ExitEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FileReq>::event_type<ErrorEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<PrepareHandle>::event_type<PrepareEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<TCPHandle>::event_type<ConnectEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsEventHandle>::event_type<ErrorEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FileReq>::event_type<FsEvent<(details::UVFsType) 15> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsEventHandle>::event_type<FsEventEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<TimerHandle>::event_type<ErrorEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<TCPHandle>::event_type<ErrorEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<GetNameInfoReq>::event_type<ErrorEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<PrepareHandle>::event_type<ErrorEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<WorkReq>::event_type<ErrorEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<PollHandle>::event_type<PollEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<PollHandle>::event_type<CloseEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<SignalHandle>::event_type<SignalEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<PipeHandle>::event_type<ConnectEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<details::ShutdownReq>::event_type<ShutdownEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FileReq>::event_type<FsEvent<(details::UVFsType) 5> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<TTYHandle>::event_type<CloseEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<UDPHandle>::event_type<CloseEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<Loop>::event_type<ErrorEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<UDPHandle>::event_type<SendEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<PipeHandle>::event_type<CloseEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsPollHandle>::event_type<ErrorEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<GetAddrInfoReq>::event_type<AddrInfoEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<details::ConnectReq>::event_type<ConnectEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<UDPHandle>::event_type<UDPDataEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<details::ConnectReq>::event_type<ErrorEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FileReq>::event_type<FsEvent<(details::UVFsType) 14> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FsPollHandle>::event_type<FsPollEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FileReq>::event_type<FsEvent<(details::UVFsType) 16> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<GetAddrInfoReq>::event_type<ErrorEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<UDPHandle>::event_type<ErrorEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FileReq>::event_type<FsEvent<(details::UVFsType) 1> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<details::SendReq>::event_type<SendEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<SignalHandle>::event_type<ErrorEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FileReq>::event_type<FsEvent<(details::UVFsType) 2> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FileReq>::event_type<FsEvent<(details::UVFsType) 3> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FileReq>::event_type<FsEvent<(details::UVFsType) 8> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<FileReq>::event_type<FsEvent<(details::UVFsType) 4> >() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<ProcessHandle>::event_type<CloseEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<ProcessHandle>::event_type<ErrorEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<TTYHandle>::event_type<ErrorEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<PollHandle>::event_type<ErrorEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<PipeHandle>::event_type<ErrorEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<CheckHandle>::event_type<CheckEvent>() noexcept;
+ extern template UVW_EXTERN std::size_t details::type_factory<CheckHandle>::event_type<CloseEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<AsyncHandle>::event_type<CloseEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<PrepareHandle>::event_type<CloseEvent>() noexcept;
+ extern template UVW_EXTERN std::size_t details::type_factory<FsEventHandle>::event_type<CloseEvent>() noexcept;
+ extern template UVW_EXTERN std::size_t details::type_factory<FsPollHandle>::event_type<CloseEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<TCPHandle>::event_type<WriteEvent>() noexcept;
+ extern template UVW_EXTERN std::size_t details::type_factory<TCPHandle>::event_type<EndEvent>() noexcept;
+ extern template UVW_EXTERN std::size_t details::type_factory<TCPHandle>::event_type<DataEvent>() noexcept;
+ extern template UVW_EXTERN std::size_t details::type_factory<TCPHandle>::event_type<ListenEvent>() noexcept;
+ extern template UVW_EXTERN std::size_t details::type_factory<TCPHandle>::event_type<ShutdownEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<TTYHandle>::event_type<WriteEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<PipeHandle>::event_type<WriteEvent>() noexcept;
+ extern template UVW_EXTERN std::size_t details::type_factory<PipeHandle>::event_type<EndEvent>() noexcept;
+ extern template UVW_EXTERN std::size_t details::type_factory<PipeHandle>::event_type<DataEvent>() noexcept;
+ extern template UVW_EXTERN std::size_t details::type_factory<PipeHandle>::event_type<ListenEvent>() noexcept;
+ extern template UVW_EXTERN std::size_t details::type_factory<PipeHandle>::event_type<ShutdownEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<SignalHandle>::event_type<CheckEvent>() noexcept;
+ extern template UVW_EXTERN std::size_t details::type_factory<SignalHandle>::event_type<CloseEvent>() noexcept;
+ extern template UVW_EXTERN std::size_t details::type_factory<FakeHandle>::event_type<CloseEvent>() noexcept;
+ extern template UVW_EXTERN std::size_t details::type_factory<FakeHandle>::event_type<ErrorEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<TestEmitter>::event_type<FakeEvent>() noexcept;
+ extern template UVW_EXTERN std::size_t details::type_factory<TestEmitter>::event_type<ErrorEvent>() noexcept;
+
+
+ extern template UVW_EXTERN std::size_t details::type_factory<WriteReq<std::default_delete<char []> > >::event_type<ErrorEvent>() noexcept;
+ extern template UVW_EXTERN std::size_t details::type_factory<WriteReq<std::default_delete<char []> > >::event_type<WriteEvent>() noexcept;
+
+ extern template UVW_EXTERN std::size_t details::type_factory<WriteReq<void (*)(char*) > >::event_type<ErrorEvent>() noexcept;
+ extern template UVW_EXTERN std::size_t details::type_factory<WriteReq<void (*)(char*) > >::event_type<WriteEvent>() noexcept;
+}
diff --git a/src/uvw/async.h b/src/uvw/async.h
index e326bac..4e6f4e3 100644
--- a/src/uvw/async.h
+++ b/src/uvw/async.h
@@ -5,7 +5,9 @@
#include <uv.h>
#include "handle.hpp"
#include "loop.h"
+#include "config.h"
+UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
namespace uvw {
@@ -15,7 +17,7 @@ namespace uvw {
*
* It will be emitted by AsyncHandle according with its functionalities.
*/
-struct AsyncEvent {};
+struct UVW_EXTERN AsyncEvent {};
/**
@@ -26,7 +28,7 @@ struct AsyncEvent {};
*
* To create an `AsyncHandle` through a `Loop`, no arguments are required.
*/
-class AsyncHandle final: public Handle<AsyncHandle, uv_async_t> {
+class UVW_EXTERN AsyncHandle final : public Handle<AsyncHandle, uv_async_t> {
static void sendCallback(uv_async_t *handle);
public:
@@ -63,4 +65,6 @@ class AsyncHandle final: public Handle<AsyncHandle, uv_async_t> {
#include "async.cpp"
#endif
+UVW_MSVC_WARNING_POP();
+
#endif // UVW_ASYNC_INCLUDE_H
diff --git a/src/uvw/check.h b/src/uvw/check.h
index 4d3e571..79f6d37 100644
--- a/src/uvw/check.h
+++ b/src/uvw/check.h
@@ -5,7 +5,9 @@
#include <uv.h>
#include "handle.hpp"
#include "loop.h"
+#include "config.h"
+UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
namespace uvw {
@@ -15,7 +17,7 @@ namespace uvw {
*
* It will be emitted by CheckHandle according with its functionalities.
*/
-struct CheckEvent {};
+struct UVW_EXTERN CheckEvent {};
/**
@@ -26,7 +28,7 @@ struct CheckEvent {};
*
* To create a `CheckHandle` through a `Loop`, no arguments are required.
*/
-class CheckHandle final: public Handle<CheckHandle, uv_check_t> {
+class UVW_EXTERN CheckHandle final : public Handle<CheckHandle, uv_check_t> {
static void startCallback(uv_check_t *handle);
public:
@@ -60,4 +62,6 @@ class CheckHandle final: public Handle<CheckHandle, uv_check_t> {
#include "check.cpp"
#endif
+UVW_MSVC_WARNING_POP();
+
#endif // UVW_CHECK_INCLUDE_H
diff --git a/src/uvw/config.h b/src/uvw/config.h
index cfee0c9..429f8fe 100644
--- a/src/uvw/config.h
+++ b/src/uvw/config.h
@@ -1,12 +1,48 @@
#ifndef UVW_CONFIG_H
#define UVW_CONFIG_H
+#if defined(BUILDING_UVW_SHARED) && defined(USING_UVW_SHARED)
+#error "Define either BUILDING_UVW_SHARED or USING_UVW_SHARED, not both."
+#endif
#ifndef UVW_AS_LIB
#define UVW_INLINE inline
+#define UVW_EXTERN /* nothing */
+#else /* UVW_AS_LIB */
+#define UVW_INLINE /* nothing */
+
+#ifdef _WIN32
+/* Windows - set up dll import/export decorators. */
+#if defined(BUILDING_UVW_SHARED)
+/* Building shared library. */
+#define UVW_EXTERN __declspec(dllexport)
+#elif defined(USING_UVW_SHARED)
+/* Using shared library. */
+#define UVW_EXTERN __declspec(dllimport)
+#else
+/* Building static library. */
+#define UVW_EXTERN /* nothing */
+#endif
+#elif __GNUC__ >= 4
+#define UVW_EXTERN __attribute__((visibility("default")))
#else
-#define UVW_INLINE
+#define UVW_EXTERN /* nothing */
#endif
+#endif /* UVW_AS_LIB */
+
+#if defined(_MSC_VER) && defined(UVW_AS_LIB)
+/*
+ * C4251: 'type' : class 'type1' needs to have dll-interface to be used by clients of class 'type2'
+ */
+#define UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE() \
+ __pragma(warning(push)) \
+ __pragma(warning(disable: 4251))
+#define UVW_MSVC_WARNING_POP() \
+ __pragma(warning(pop))
+#else
+#define UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE()
+#define UVW_MSVC_WARNING_POP()
+#endif
#endif
diff --git a/src/uvw/dns.h b/src/uvw/dns.h
index e9b2e86..db90ddd 100644
--- a/src/uvw/dns.h
+++ b/src/uvw/dns.h
@@ -9,6 +9,9 @@
#include "request.hpp"
#include "util.h"
#include "loop.h"
+#include "config.h"
+
+UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
namespace uvw {
@@ -19,7 +22,7 @@ namespace uvw {
*
* It will be emitted by GetAddrInfoReq according with its functionalities.
*/
-struct AddrInfoEvent {
+struct UVW_EXTERN AddrInfoEvent {
using Deleter = void(*)(addrinfo *);
AddrInfoEvent(std::unique_ptr<addrinfo, Deleter> addr);
@@ -39,7 +42,7 @@ struct AddrInfoEvent {
*
* It will be emitted by GetNameInfoReq according with its functionalities.
*/
-struct NameInfoEvent {
+struct UVW_EXTERN NameInfoEvent {
NameInfoEvent(const char *host, const char *serv);
/**
@@ -68,7 +71,7 @@ struct NameInfoEvent {
*
* To create a `GetAddrInfoReq` through a `Loop`, no arguments are required.
*/
-class GetAddrInfoReq final: public Request<GetAddrInfoReq, uv_getaddrinfo_t> {
+class UVW_EXTERN GetAddrInfoReq final: public Request<GetAddrInfoReq, uv_getaddrinfo_t> {
static void addrInfoCallback(uv_getaddrinfo_t *req, int status, addrinfo *res);
void nodeAddrInfo(const char *node, const char *service, addrinfo *hints = nullptr);
auto nodeAddrInfoSync(const char *node, const char *service, addrinfo *hints = nullptr);
@@ -153,7 +156,7 @@ class GetAddrInfoReq final: public Request<GetAddrInfoReq, uv_getaddrinfo_t> {
*
* To create a `GetNameInfoReq` through a `Loop`, no arguments are required.
*/
-class GetNameInfoReq final: public Request<GetNameInfoReq, uv_getnameinfo_t> {
+class UVW_EXTERN GetNameInfoReq final: public Request<GetNameInfoReq, uv_getnameinfo_t> {
static void nameInfoCallback(uv_getnameinfo_t *req, int status, const char *hostname, const char *service);
public:
@@ -232,17 +235,17 @@ class GetNameInfoReq final: public Request<GetNameInfoReq, uv_getnameinfo_t> {
// (extern) explicit instantiations
-extern template void GetNameInfoReq::nameInfo<IPv4>(std::string ip, unsigned int port, int flags);
-extern template void GetNameInfoReq::nameInfo<IPv6>(std::string ip, unsigned int port, int flags);
+extern template UVW_EXTERN void GetNameInfoReq::nameInfo<IPv4>(std::string ip, unsigned int port, int flags);
+extern template UVW_EXTERN void GetNameInfoReq::nameInfo<IPv6>(std::string ip, unsigned int port, int flags);
-extern template void GetNameInfoReq::nameInfo<IPv4>(Addr addr, int flags);
-extern template void GetNameInfoReq::nameInfo<IPv6>(Addr addr, int flags);
+extern template UVW_EXTERN void GetNameInfoReq::nameInfo<IPv4>(Addr addr, int flags);
+extern template UVW_EXTERN void GetNameInfoReq::nameInfo<IPv6>(Addr addr, int flags);
-extern template std::pair<bool, std::pair<const char *, const char *>> GetNameInfoReq::nameInfoSync<IPv4>(std::string ip, unsigned int port, int flags);
-extern template std::pair<bool, std::pair<const char *, const char *>> GetNameInfoReq::nameInfoSync<IPv6>(std::string ip, unsigned int port, int flags);
+extern template UVW_EXTERN std::pair<bool, std::pair<const char *, const char *>> GetNameInfoReq::nameInfoSync<IPv4>(std::string ip, unsigned int port, int flags);
+extern template UVW_EXTERN std::pair<bool, std::pair<const char *, const char *>> GetNameInfoReq::nameInfoSync<IPv6>(std::string ip, unsigned int port, int flags);
-extern template std::pair<bool, std::pair<const char *, const char *>> GetNameInfoReq::nameInfoSync<IPv4>(Addr addr, int flags);
-extern template std::pair<bool, std::pair<const char *, const char *>> GetNameInfoReq::nameInfoSync<IPv6>(Addr addr, int flags);
+extern template UVW_EXTERN std::pair<bool, std::pair<const char *, const char *>> GetNameInfoReq::nameInfoSync<IPv4>(Addr addr, int flags);
+extern template UVW_EXTERN std::pair<bool, std::pair<const char *, const char *>> GetNameInfoReq::nameInfoSync<IPv6>(Addr addr, int flags);
}
@@ -252,4 +255,6 @@ extern template std::pair<bool, std::pair<const char *, const char *>> GetNameIn
#include "dns.cpp"
#endif
+UVW_MSVC_WARNING_POP();
+
#endif // UVW_DNS_INCLUDE_H
diff --git a/src/uvw/emitter.h b/src/uvw/emitter.h
index a189f3a..e7ade99 100644
--- a/src/uvw/emitter.h
+++ b/src/uvw/emitter.h
@@ -12,6 +12,11 @@
#include <list>
#include <uv.h>
+#include "config.h"
+#include "type_factory/type_factory.h"
+
+UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
+
namespace uvw {
@@ -21,7 +26,7 @@ namespace uvw {
*
* Custom wrapper around error constants of `libuv`.
*/
-struct ErrorEvent {
+struct UVW_EXTERN ErrorEvent {
template<typename U, typename = std::enable_if_t<std::is_integral_v<U>>>
explicit ErrorEvent(U val) noexcept
: ec{static_cast<int>(val)}
@@ -157,20 +162,9 @@ class Emitter {
ListenerList onL{};
};
- static std::size_t next_type() noexcept {
- static std::size_t counter = 0;
- return counter++;
- }
-
- template<typename>
- static std::size_t event_type() noexcept {
- static std::size_t value = next_type();
- return value;
- }
-
template<typename E>
Handler<E> & handler() noexcept {
- std::size_t type = event_type<E>();
+ std::size_t type = details::type_factory<T>::template event_type<E>();
if(!(type < handlers.size())) {
handlers.resize(type+1);
@@ -190,6 +184,14 @@ class Emitter {
}
public:
+ Emitter() = default;
+ Emitter(Emitter &&) = default;
+ Emitter & operator=(Emitter &&) = default;
+
+ // These must be deleted because MSVC try to export them with UVW_EXPORT
+ Emitter(const Emitter&) = delete;
+ Emitter& operator=(const Emitter&) = delete;
+
template<typename E>
using Listener = typename Handler<E>::Listener;
@@ -292,7 +294,7 @@ class Emitter {
*/
template<typename E>
bool empty() const noexcept {
- std::size_t type = event_type<E>();
+ std::size_t type = details::type_factory<T>::template event_type<E>();
return (!(type < handlers.size()) ||
!handlers[type] ||
@@ -316,9 +318,16 @@ class Emitter {
}
+struct UVW_EXTERN FakeEvent { };
+
+struct UVW_EXTERN TestEmitter: uvw::Emitter<TestEmitter> {
+ void emit() { publish(FakeEvent{}); }
+};
#ifndef UVW_AS_LIB
#include "emitter.cpp"
#endif
+UVW_MSVC_WARNING_POP();
+
#endif // UVW_EMITTER_INCLUDE_H
diff --git a/src/uvw/fs.h b/src/uvw/fs.h
index c4af1d4..d4a1ea1 100644
--- a/src/uvw/fs.h
+++ b/src/uvw/fs.h
@@ -10,6 +10,9 @@
#include "request.hpp"
#include "util.h"
#include "loop.h"
+#include "config.h"
+
+UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
namespace uvw {
@@ -433,7 +436,7 @@ class FsRequest: public Request<T, uv_fs_t> {
* [documentation](http://docs.libuv.org/en/v1.x/fs.html)
* for further details.
*/
-class FileReq final: public FsRequest<FileReq> {
+class UVW_EXTERN FileReq final: public FsRequest<FileReq> {
static constexpr uv_file BAD_FD = -1;
static void fsOpenCallback(uv_fs_t *req);
@@ -784,7 +787,7 @@ class FileReq final: public FsRequest<FileReq> {
* [documentation](http://docs.libuv.org/en/v1.x/fs.html)
* for further details.
*/
-class FsReq final: public FsRequest<FsReq> {
+class UVW_EXTERN FsReq final: public FsRequest<FsReq> {
static void fsReadlinkCallback(uv_fs_t *req);
static void fsReaddirCallback(uv_fs_t *req);
@@ -1425,7 +1428,7 @@ class FsReq final: public FsRequest<FsReq> {
/*! @brief Helper functions. */
-struct FsHelper {
+struct UVW_EXTERN FsHelper {
/**
* @brief Gets the OS dependent handle.
*
@@ -1459,4 +1462,6 @@ struct FsHelper {
#include "fs.cpp"
#endif
+UVW_MSVC_WARNING_POP();
+
#endif // UVW_FS_INCLUDE_H
diff --git a/src/uvw/fs_event.h b/src/uvw/fs_event.h
index 6cbc5a0..ba15842 100644
--- a/src/uvw/fs_event.h
+++ b/src/uvw/fs_event.h
@@ -8,6 +8,9 @@
#include "handle.hpp"
#include "util.h"
#include "loop.h"
+#include "config.h"
+
+UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
namespace uvw {
@@ -37,7 +40,7 @@ enum class UVFsEvent: std::underlying_type_t<uv_fs_event> {
*
* It will be emitted by FsEventHandle according with its functionalities.
*/
-struct FsEventEvent {
+struct UVW_EXTERN FsEventEvent {
FsEventEvent(const char * pathname, Flags<details::UVFsEvent> events);
/**
@@ -58,6 +61,7 @@ struct FsEventEvent {
*/
Flags<details::UVFsEvent> flags;
};
+template class UVW_EXTERN Flags<details::UVFsEvent>;
/**
@@ -73,7 +77,7 @@ struct FsEventEvent {
* [documentation](http://docs.libuv.org/en/v1.x/fs_event.html)
* for further details.
*/
-class FsEventHandle final: public Handle<FsEventHandle, uv_fs_event_t> {
+class UVW_EXTERN FsEventHandle final: public Handle<FsEventHandle, uv_fs_event_t> {
static void startCallback(uv_fs_event_t *handle, const char *filename, int events, int status);
public:
@@ -146,4 +150,6 @@ class FsEventHandle final: public Handle<FsEventHandle, uv_fs_event_t> {
#include "fs_event.cpp"
#endif
+UVW_MSVC_WARNING_POP();
+
#endif // UVW_FS_EVENT_INCLUDE_H
diff --git a/src/uvw/fs_poll.h b/src/uvw/fs_poll.h
index a264eb3..365669b 100644
--- a/src/uvw/fs_poll.h
+++ b/src/uvw/fs_poll.h
@@ -8,6 +8,9 @@
#include "handle.hpp"
#include "util.h"
#include "loop.h"
+#include "config.h"
+
+UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
namespace uvw {
@@ -18,7 +21,7 @@ namespace uvw {
*
* It will be emitted by FsPollHandle according with its functionalities.
*/
-struct FsPollEvent {
+struct UVW_EXTERN FsPollEvent {
explicit FsPollEvent(Stat previous, Stat current) noexcept;
Stat prev; /*!< The old Stat struct. */
@@ -35,7 +38,7 @@ struct FsPollEvent {
*
* To create a `FsPollHandle` through a `Loop`, no arguments are required.
*/
-class FsPollHandle final: public Handle<FsPollHandle, uv_fs_poll_t> {
+class UVW_EXTERN FsPollHandle final: public Handle<FsPollHandle, uv_fs_poll_t> {
static void startCallback(uv_fs_poll_t *handle, int status, const uv_stat_t *prev, const uv_stat_t *curr);
public:
@@ -80,4 +83,6 @@ class FsPollHandle final: public Handle<FsPollHandle, uv_fs_poll_t> {
#include "fs_poll.cpp"
#endif
+UVW_MSVC_WARNING_POP();
+
#endif // UVW_FS_POLL_INCLUDE_H
diff --git a/src/uvw/handle.hpp b/src/uvw/handle.hpp
index 274f4fc..17d059c 100644
--- a/src/uvw/handle.hpp
+++ b/src/uvw/handle.hpp
@@ -8,6 +8,9 @@
#include <uv.h>
#include "resource.hpp"
#include "util.h"
+#include "config.h"
+
+UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
namespace uvw {
@@ -18,7 +21,7 @@ namespace uvw {
*
* It will be emitted by the handles according with their functionalities.
*/
-struct CloseEvent {};
+struct UVW_EXTERN CloseEvent {};
/**
@@ -274,4 +277,15 @@ class Handle: public Resource<T, U>, public BaseHandle {
}
+struct fake_handle_t { void *data; };
+
+struct UVW_EXTERN FakeHandle: uvw::Handle<FakeHandle, fake_handle_t> {
+ using Handle::Handle;
+
+ template<typename... Args>
+ bool init(Args&&...) { return initialize([](auto...){ return true; }); }
+};
+
+UVW_MSVC_WARNING_POP();
+
#endif // UVW_HANDLE_INCLUDE_H
diff --git a/src/uvw/idle.h b/src/uvw/idle.h
index 28a8c12..af78ce1 100644
--- a/src/uvw/idle.h
+++ b/src/uvw/idle.h
@@ -5,6 +5,9 @@
#include <uv.h>
#include "handle.hpp"
#include "loop.h"
+#include "config.h"
+
+UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
namespace uvw {
@@ -15,7 +18,7 @@ namespace uvw {
*
* It will be emitted by IdleHandle according with its functionalities.
*/
-struct IdleEvent {};
+struct UVW_EXTERN IdleEvent {};
/**
@@ -34,7 +37,7 @@ struct IdleEvent {};
*
* To create an `IdleHandle` through a `Loop`, no arguments are required.
*/
-class IdleHandle final: public Handle<IdleHandle, uv_idle_t> {
+class UVW_EXTERN IdleHandle final: public Handle<IdleHandle, uv_idle_t> {
static void startCallback(uv_idle_t *handle);
public:
@@ -68,4 +71,6 @@ class IdleHandle final: public Handle<IdleHandle, uv_idle_t> {
#include "idle.cpp"
#endif
+UVW_MSVC_WARNING_POP();
+
#endif // UVW_IDLE_INCLUDE_H
diff --git a/src/uvw/lib.h b/src/uvw/lib.h
index 7e8fff1..b8e293d 100644
--- a/src/uvw/lib.h
+++ b/src/uvw/lib.h
@@ -8,6 +8,9 @@
#include <uv.h>
#include "loop.h"
#include "underlying_type.hpp"
+#include "config.h"
+
+UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
namespace uvw {
@@ -19,7 +22,7 @@ namespace uvw {
* `uvw` provides cross platform utilities for loading shared libraries and
* retrieving symbols from them, by means of the API offered by `libuv`.
*/
-class SharedLib final: public UnderlyingType<SharedLib, uv_lib_t> {
+class UVW_EXTERN SharedLib final: public UnderlyingType<SharedLib, uv_lib_t> {
public:
explicit SharedLib(ConstructorAccess ca, std::shared_ptr<Loop> ref, std::string filename) noexcept;
@@ -67,4 +70,6 @@ class SharedLib final: public UnderlyingType<SharedLib, uv_lib_t> {
#include "lib.cpp"
#endif
+UVW_MSVC_WARNING_POP();
+
#endif // UVW_LIB_INCLUDE_H
diff --git a/src/uvw/loop.h b/src/uvw/loop.h
index 9832f0f..94c3a03 100644
--- a/src/uvw/loop.h
+++ b/src/uvw/loop.h
@@ -14,6 +14,9 @@
#include <uv.h>
#include "emitter.h"
#include "util.h"
+#include "config.h"
+
+UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
namespace uvw {
@@ -45,7 +48,7 @@ enum class UVRunMode: std::underlying_type_t<uv_run_mode> {
* users walk them as untyped instances.<br/>
* This can help to end all the pending requests by closing the handles.
*/
-struct BaseHandle {
+struct UVW_EXTERN BaseHandle {
/**
* @brief Gets the category of the handle.
*
@@ -140,7 +143,7 @@ struct BaseHandle {
* It takes care of polling for I/O and scheduling callbacks to be run based on
* different sources of events.
*/
-class Loop final: public Emitter<Loop>, public std::enable_shared_from_this<Loop> {
+class UVW_EXTERN Loop final: public Emitter<Loop>, public std::enable_shared_from_this<Loop> {
using Deleter = void(*)(uv_loop_t *);
template<typename, typename>
@@ -425,9 +428,9 @@ class Loop final: public Emitter<Loop>, public std::enable_shared_from_this<Loop
// (extern) explicit instantiations
-extern template bool Loop::run<Loop::Mode::DEFAULT>() noexcept;
-extern template bool Loop::run<Loop::Mode::ONCE>() noexcept;
-extern template bool Loop::run<Loop::Mode::NOWAIT>() noexcept;
+extern template UVW_EXTERN bool Loop::run<Loop::Mode::DEFAULT>() noexcept;
+extern template UVW_EXTERN bool Loop::run<Loop::Mode::ONCE>() noexcept;
+extern template UVW_EXTERN bool Loop::run<Loop::Mode::NOWAIT>() noexcept;
}
@@ -437,4 +440,6 @@ extern template bool Loop::run<Loop::Mode::NOWAIT>() noexcept;
#include "loop.cpp"
#endif
+UVW_MSVC_WARNING_POP();
+
#endif // UVW_LOOP_INCLUDE_H
diff --git a/src/uvw/pipe.h b/src/uvw/pipe.h
index d37ea40..c71c9dc 100644
--- a/src/uvw/pipe.h
+++ b/src/uvw/pipe.h
@@ -10,6 +10,9 @@
#include "stream.h"
#include "util.h"
#include "loop.h"
+#include "config.h"
+
+UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
namespace uvw {
@@ -38,7 +41,7 @@ enum class UVChmodFlags: std::underlying_type_t<uv_poll_event> {
* * An optional boolean value that indicates if this pipe will be used for
* handle passing between processes.
*/
-class PipeHandle final: public StreamHandle<PipeHandle, uv_pipe_t> {
+class UVW_EXTERN PipeHandle final: public StreamHandle<PipeHandle, uv_pipe_t> {
public:
using Chmod = details::UVChmodFlags;
@@ -164,4 +167,6 @@ class PipeHandle final: public StreamHandle<PipeHandle, uv_pipe_t> {
#include "pipe.cpp"
#endif
+UVW_MSVC_WARNING_POP();
+
#endif // UVW_PIPE_INCLUDE_H
diff --git a/src/uvw/poll.h b/src/uvw/poll.h
index 6030fd5..f12a25f 100644
--- a/src/uvw/poll.h
+++ b/src/uvw/poll.h
@@ -7,6 +7,9 @@
#include <uv.h>
#include "handle.hpp"
#include "util.h"
+#include "config.h"
+
+UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
namespace uvw {
@@ -31,7 +34,7 @@ enum class UVPollEvent: std::underlying_type_t<uv_poll_event> {
*
* It will be emitted by PollHandle according with its functionalities.
*/
-struct PollEvent {
+struct UVW_EXTERN PollEvent {
explicit PollEvent(Flags<details::UVPollEvent> events) noexcept;
/**
@@ -46,6 +49,7 @@ struct PollEvent {
*/
Flags<details::UVPollEvent> flags;
};
+template class UVW_EXTERN Flags<details::UVPollEvent>;
/**
@@ -64,7 +68,7 @@ struct PollEvent {
* [documentation](http://docs.libuv.org/en/v1.x/poll.html)
* for further details.
*/
-class PollHandle final: public Handle<PollHandle, uv_poll_t> {
+class UVW_EXTERN PollHandle final: public Handle<PollHandle, uv_poll_t> {
static void startCallback(uv_poll_t *handle, int status, int events);
public:
@@ -142,4 +146,6 @@ class PollHandle final: public Handle<PollHandle, uv_poll_t> {
#include "poll.cpp"
#endif
+UVW_MSVC_WARNING_POP();
+
#endif // UVW_POLL_INCLUDE_H
diff --git a/src/uvw/prepare.h b/src/uvw/prepare.h
index 736c7b8..9aab6e2 100644
--- a/src/uvw/prepare.h
+++ b/src/uvw/prepare.h
@@ -5,6 +5,9 @@
#include <uv.h>
#include "handle.hpp"
#include "loop.h"
+#include "config.h"
+
+UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
namespace uvw {
@@ -15,7 +18,7 @@ namespace uvw {
*
* It will be emitted by PrepareHandle according with its functionalities.
*/
-struct PrepareEvent {};
+struct UVW_EXTERN PrepareEvent {};
/**
@@ -26,7 +29,7 @@ struct PrepareEvent {};
*
* To create a `PrepareHandle` through a `Loop`, no arguments are required.
*/
-class PrepareHandle final: public Handle<PrepareHandle, uv_prepare_t> {
+class UVW_EXTERN PrepareHandle final: public Handle<PrepareHandle, uv_prepare_t> {
static void startCallback(uv_prepare_t *handle);
public:
@@ -62,4 +65,6 @@ class PrepareHandle final: public Handle<PrepareHandle, uv_prepare_t> {
#include "prepare.cpp"
#endif
+UVW_MSVC_WARNING_POP();
+
#endif // UVW_PREPARE_INCLUDE_H
diff --git a/src/uvw/process.h b/src/uvw/process.h
index f19fcc4..378a934 100644
--- a/src/uvw/process.h
+++ b/src/uvw/process.h
@@ -11,6 +11,9 @@
#include "stream.h"
#include "util.h"
#include "loop.h"
+#include "config.h"
+
+UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
namespace uvw {
@@ -49,7 +52,7 @@ enum class UVStdIOFlags: std::underlying_type_t<uv_stdio_flags> {
*
* It will be emitted by ProcessHandle according with its functionalities.
*/
-struct ExitEvent {
+struct UVW_EXTERN ExitEvent {
explicit ExitEvent(int64_t code, int sig) noexcept;
int64_t status; /*!< The exit status. */
@@ -62,7 +65,7 @@ struct ExitEvent {
* Process handles will spawn a new process and allow the user to control it and
* establish communication channels with it using streams.
*/
-class ProcessHandle final: public Handle<ProcessHandle, uv_process_t> {
+class UVW_EXTERN ProcessHandle final: public Handle<ProcessHandle, uv_process_t> {
static void exitCallback(uv_process_t *handle, int64_t exitStatus, int termSignal);
public:
@@ -242,6 +245,7 @@ class ProcessHandle final: public Handle<ProcessHandle, uv_process_t> {
Uid poUid;
Gid poGid;
};
+template class UVW_EXTERN Flags<ProcessHandle::Process>;
}
@@ -251,4 +255,6 @@ class ProcessHandle final: public Handle<ProcessHandle, uv_process_t> {
#include "process.cpp"
#endif
+UVW_MSVC_WARNING_POP();
+
#endif // UVW_PROCESS_INCLUDE_H
diff --git a/src/uvw/request.hpp b/src/uvw/request.hpp
index 212ad39..2dd773d 100644
--- a/src/uvw/request.hpp
+++ b/src/uvw/request.hpp
@@ -7,6 +7,9 @@
#include <memory>
#include <uv.h>
#include "resource.hpp"
+#include "config.h"
+
+UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
namespace uvw {
@@ -72,4 +75,6 @@ class Request: public Resource<T, U> {
}
+UVW_MSVC_WARNING_POP();
+
#endif // UVW_REQUEST_INCLUDE_H
diff --git a/src/uvw/resource.hpp b/src/uvw/resource.hpp
index 53c8adb..4f6d4ed 100644
--- a/src/uvw/resource.hpp
+++ b/src/uvw/resource.hpp
@@ -6,6 +6,9 @@
#include <utility>
#include "emitter.h"
#include "underlying_type.hpp"
+#include "config.h"
+
+UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
namespace uvw {
@@ -70,4 +73,6 @@ class Resource: public UnderlyingType<T, U>, public Emitter<T>, public std::enab
}
+UVW_MSVC_WARNING_POP();
+
#endif // UVW_RESOURCE_INCLUDE_H
diff --git a/src/uvw/signal.h b/src/uvw/signal.h
index 93b6905..d357d14 100644
--- a/src/uvw/signal.h
+++ b/src/uvw/signal.h
@@ -5,6 +5,9 @@
#include <uv.h>
#include "handle.hpp"
#include "loop.h"
+#include "config.h"
+
+UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
namespace uvw {
@@ -15,7 +18,7 @@ namespace uvw {
*
* It will be emitted by SignalHandle according with its functionalities.
*/
-struct SignalEvent {
+struct UVW_EXTERN SignalEvent {
explicit SignalEvent(int sig) noexcept;
int signum; /*!< The signal being monitored by this handle. */
@@ -35,7 +38,7 @@ struct SignalEvent {
* [documentation](http://docs.libuv.org/en/v1.x/signal.html)
* for further details.
*/
-class SignalHandle final: public Handle<SignalHandle, uv_signal_t> {
+class UVW_EXTERN SignalHandle final: public Handle<SignalHandle, uv_signal_t> {
static void startCallback(uv_signal_t *handle, int signum);
public:
@@ -86,4 +89,6 @@ class SignalHandle final: public Handle<SignalHandle, uv_signal_t> {
#include "signal.cpp"
#endif
+UVW_MSVC_WARNING_POP();
+
#endif // UVW_SIGNAL_INCLUDE_H
diff --git a/src/uvw/stream.cpp b/src/uvw/stream.cpp
index 4d558e0..323f8d6 100644
--- a/src/uvw/stream.cpp
+++ b/src/uvw/stream.cpp
@@ -7,6 +7,16 @@
namespace uvw {
+ template<typename Deleter>
+ UVW_INLINE void WriteReq<Deleter>::write(uv_stream_t *handle) {
+ this->invoke(&uv_write, this->get(), handle, &buf, 1, &this->template defaultCallback<WriteEvent>);
+ }
+
+ template<typename Deleter>
+ UVW_INLINE void WriteReq<Deleter>::write(uv_stream_t *handle, uv_stream_t *send) {
+ this->invoke(&uv_write2, this->get(), handle, &buf, 1, send, &this->template defaultCallback<WriteEvent>);
+ }
+
UVW_INLINE DataEvent::DataEvent(std::unique_ptr<char[]> buf, std::size_t len) noexcept
: data{std::move(buf)}, length{len}
@@ -17,5 +27,8 @@ UVW_INLINE void details::ShutdownReq::shutdown(uv_stream_t *handle) {
invoke(&uv_shutdown, get(), handle, &defaultCallback<ShutdownEvent>);
}
+template void WriteReq<std::default_delete<char []> >::write(uv_stream_s*);
+template void WriteReq<void (*)(char*)>::write(uv_stream_s*);
+template void WriteReq<std::default_delete<char []> >::write(uv_stream_t *handle, uv_stream_t *send);
}
diff --git a/src/uvw/stream.h b/src/uvw/stream.h
index 88d6dc1..66b1d6d 100644
--- a/src/uvw/stream.h
+++ b/src/uvw/stream.h
@@ -11,6 +11,9 @@
#include "request.hpp"
#include "handle.hpp"
#include "loop.h"
+#include "config.h"
+
+UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
namespace uvw {
@@ -21,7 +24,7 @@ namespace uvw {
*
* It will be emitted by StreamHandle according with its functionalities.
*/
-struct ConnectEvent {};
+struct UVW_EXTERN ConnectEvent {};
/**
@@ -29,7 +32,7 @@ struct ConnectEvent {};
*
* It will be emitted by StreamHandle according with its functionalities.
*/
-struct EndEvent {};
+struct UVW_EXTERN EndEvent {};
/**
@@ -37,7 +40,7 @@ struct EndEvent {};
*
* It will be emitted by StreamHandle according with its functionalities.
*/
-struct ListenEvent {};
+struct UVW_EXTERN ListenEvent {};
/**
@@ -45,7 +48,7 @@ struct ListenEvent {};
*
* It will be emitted by StreamHandle according with its functionalities.
*/
-struct ShutdownEvent {};
+struct UVW_EXTERN ShutdownEvent {};
/**
@@ -53,7 +56,7 @@ struct ShutdownEvent {};
*
* It will be emitted by StreamHandle according with its functionalities.
*/
-struct WriteEvent {};
+struct UVW_EXTERN WriteEvent {};
/**
@@ -61,7 +64,7 @@ struct WriteEvent {};
*
* It will be emitted by StreamHandle according with its functionalities.
*/
-struct DataEvent {
+struct UVW_EXTERN DataEvent {
explicit DataEvent(std::unique_ptr<char[]> buf, std::size_t len) noexcept;
std::unique_ptr<char[]> data; /*!< A bunch of data read on the stream. */
@@ -72,7 +75,7 @@ struct DataEvent {
namespace details {
-struct ConnectReq final: public Request<ConnectReq, uv_connect_t> {
+struct UVW_EXTERN ConnectReq final: public Request<ConnectReq, uv_connect_t> {
using Request::Request;
template<typename F, typename... Args>
@@ -82,40 +85,37 @@ struct ConnectReq final: public Request<ConnectReq, uv_connect_t> {
};
-struct ShutdownReq final: public Request<ShutdownReq, uv_shutdown_t> {
+struct UVW_EXTERN ShutdownReq final: public Request<ShutdownReq, uv_shutdown_t> {
using Request::Request;
void shutdown(uv_stream_t *handle);
};
-template<typename Deleter>
-class WriteReq final: public Request<WriteReq<Deleter>, uv_write_t> {
- using ConstructorAccess = typename Request<WriteReq<Deleter>, uv_write_t>::ConstructorAccess;
-public:
- WriteReq(ConstructorAccess ca, std::shared_ptr<Loop> loop, std::unique_ptr<char[], Deleter> dt, unsigned int len)
- : Request<WriteReq<Deleter>, uv_write_t>{ca, std::move(loop)},
- data{std::move(dt)},
- buf{uv_buf_init(data.get(), len)}
- {}
- void write(uv_stream_t *handle) {
- this->invoke(&uv_write, this->get(), handle, &buf, 1, &this->template defaultCallback<WriteEvent>);
- }
+}
- void write(uv_stream_t *handle, uv_stream_t *send) {
- this->invoke(&uv_write2, this->get(), handle, &buf, 1, send, &this->template defaultCallback<WriteEvent>);
- }
+ template<typename Deleter>
+ class UVW_EXTERN WriteReq final: public Request<WriteReq<Deleter>, uv_write_t> {
+ using ConstructorAccess = typename Request<WriteReq<Deleter>, uv_write_t>::ConstructorAccess;
-private:
- std::unique_ptr<char[], Deleter> data;
- uv_buf_t buf;
-};
+ public:
+ WriteReq(WriteReq::ConstructorAccess ca, std::shared_ptr<Loop> loop,
+ std::unique_ptr<char[], Deleter> dt, unsigned int len)
+ : Request<WriteReq<Deleter>, uv_write_t>{ca, std::move(loop)},
+ data{std::move(dt)},
+ buf{uv_buf_init(data.get(), len)}
+ {}
+ void write(uv_stream_t *handle);
-}
+ void write(uv_stream_t *handle, uv_stream_t *send);
+ private:
+ std::unique_ptr<char[], Deleter> data;
+ uv_buf_t buf;
+ };
/**
* @brief The StreamHandle handle.
@@ -254,7 +254,7 @@ class StreamHandle: public Handle<T, U> {
*/
template<typename Deleter>
void write(std::unique_ptr<char[], Deleter> data, unsigned int len) {
- auto req = this->loop().template resource<details::WriteReq<Deleter>>(std::move(data), len);
+ auto req = this->loop().template resource<WriteReq<Deleter>>(std::move(data), len);
auto listener = [ptr = this->shared_from_this()](const auto &event, const auto &) {
ptr->publish(event);
};
@@ -277,7 +277,7 @@ class StreamHandle: public Handle<T, U> {
* @param len The lenght of the submitted data.
*/
void write(char *data, unsigned int len) {
- auto req = this->loop().template resource<details::WriteReq<void(*)(char *)>>(std::unique_ptr<char[], void(*)(char *)>{data, [](char *) {}}, len);
+ auto req = this->loop().template resource<WriteReq<void(*)(char *)>>(std::unique_ptr<char[], void(*)(char *)>{data, [](char *) {}}, len);
auto listener = [ptr = this->shared_from_this()](const auto &event, const auto &) {
ptr->publish(event);
};
@@ -308,7 +308,7 @@ class StreamHandle: public Handle<T, U> {
*/
template<typename S, typename Deleter>
void write(S &send, std::unique_ptr<char[], Deleter> data, unsigned int len) {
- auto req = this->loop().template resource<details::WriteReq<Deleter>>(std::move(data), len);
+ auto req = this->loop().template resource<WriteReq<Deleter>>(std::move(data), len);
auto listener = [ptr = this->shared_from_this()](const auto &event, const auto &) {
ptr->publish(event);
};
@@ -339,7 +339,7 @@ class StreamHandle: public Handle<T, U> {
*/
template<typename S>
void write(S &send, char *data, unsigned int len) {
- auto req = this->loop().template resource<details::WriteReq<void(*)(char *)>>(std::unique_ptr<char[], void(*)(char *)>{data, [](char *) {}}, len);
+ auto req = this->loop().template resource<WriteReq<void(*)(char *)>>(std::unique_ptr<char[], void(*)(char *)>{data, [](char *) {}}, len);
auto listener = [ptr = this->shared_from_this()](const auto &event, const auto &) {
ptr->publish(event);
};
@@ -439,6 +439,10 @@ class StreamHandle: public Handle<T, U> {
}
};
+extern template UVW_EXTERN void WriteReq<std::default_delete<char []> >::write(uv_stream_s*);
+extern template UVW_EXTERN void WriteReq<void (*)(char*)>::write(uv_stream_s*);
+extern template UVW_EXTERN void WriteReq<std::default_delete<char []> >::write(uv_stream_t *handle, uv_stream_t *send);
+
}
@@ -447,4 +451,6 @@ class StreamHandle: public Handle<T, U> {
#include "stream.cpp"
#endif
+UVW_MSVC_WARNING_POP();
+
#endif // UVW_STREAM_INCLUDE_H
diff --git a/src/uvw/tcp.h b/src/uvw/tcp.h
index 2b1e255..30b4a90 100644
--- a/src/uvw/tcp.h
+++ b/src/uvw/tcp.h
@@ -11,6 +11,9 @@
#include "request.hpp"
#include "stream.h"
#include "util.h"
+#include "config.h"
+
+UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
namespace uvw {
@@ -43,7 +46,7 @@ enum class UVTCPFlags: std::underlying_type_t<uv_tcp_flags> {
* [documentation](http://docs.libuv.org/en/v1.x/tcp.html#c.uv_tcp_init_ex)
* for further details.
*/
-class TCPHandle final: public StreamHandle<TCPHandle, uv_tcp_t> {
+class UVW_EXTERN TCPHandle final: public StreamHandle<TCPHandle, uv_tcp_t> {
public:
using Time = std::chrono::duration<unsigned int>;
using Bind = details::UVTCPFlags;
@@ -232,23 +235,23 @@ class TCPHandle final: public StreamHandle<TCPHandle, uv_tcp_t> {
// (extern) explicit instantiations
-extern template void TCPHandle::bind<IPv4>(std::string, unsigned int, Flags<Bind>);
-extern template void TCPHandle::bind<IPv6>(std::string, unsigned int, Flags<Bind>);
+extern template UVW_EXTERN void TCPHandle::bind<IPv4>(std::string, unsigned int, Flags<Bind>);
+extern template UVW_EXTERN void TCPHandle::bind<IPv6>(std::string, unsigned int, Flags<Bind>);
-extern template void TCPHandle::bind<IPv4>(Addr, Flags<Bind>);
-extern template void TCPHandle::bind<IPv6>(Addr, Flags<Bind>);
+extern template UVW_EXTERN void TCPHandle::bind<IPv4>(Addr, Flags<Bind>);
+extern template UVW_EXTERN void TCPHandle::bind<IPv6>(Addr, Flags<Bind>);
-extern template Addr TCPHandle::sock<IPv4>() const noexcept;
-extern template Addr TCPHandle::sock<IPv6>() const noexcept;
+extern template UVW_EXTERN Addr TCPHandle::sock<IPv4>() const noexcept;
+extern template UVW_EXTERN Addr TCPHandle::sock<IPv6>() const noexcept;
-extern template Addr TCPHandle::peer<IPv4>() const noexcept;
-extern template Addr TCPHandle::peer<IPv6>() const noexcept;
+extern template UVW_EXTERN Addr TCPHandle::peer<IPv4>() const noexcept;
+extern template UVW_EXTERN Addr TCPHandle::peer<IPv6>() const noexcept;
-extern template void TCPHandle::connect<IPv4>(std::string, unsigned int);
-extern template void TCPHandle::connect<IPv6>(std::string, unsigned int);
+extern template UVW_EXTERN void TCPHandle::connect<IPv4>(std::string, unsigned int);
+extern template UVW_EXTERN void TCPHandle::connect<IPv6>(std::string, unsigned int);
-extern template void TCPHandle::connect<IPv4>(Addr addr);
-extern template void TCPHandle::connect<IPv6>(Addr addr);
+extern template UVW_EXTERN void TCPHandle::connect<IPv4>(Addr addr);
+extern template UVW_EXTERN void TCPHandle::connect<IPv6>(Addr addr);
}
@@ -258,4 +261,6 @@ extern template void TCPHandle::connect<IPv6>(Addr addr);
#include "tcp.cpp"
#endif
+UVW_MSVC_WARNING_POP();
+
#endif // UVW_TCP_INCLUDE_H
diff --git a/src/uvw/thread.h b/src/uvw/thread.h
index 912d8a1..07481d3 100644
--- a/src/uvw/thread.h
+++ b/src/uvw/thread.h
@@ -10,6 +10,9 @@
#include <uv.h>
#include "loop.h"
#include "underlying_type.hpp"
+#include "config.h"
+
+UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
namespace uvw {
@@ -46,7 +49,7 @@ class Barrier;
* that it can be assigned to an `std::function<void(std::shared_ptr<void>)>`.
* * An optional payload the type of which is `std::shared_ptr<void>`.
*/
-class Thread final: public UnderlyingType<Thread, uv_thread_t> {
+class UVW_EXTERN Thread final: public UnderlyingType<Thread, uv_thread_t> {
using InternalTask = std::function<void(std::shared_ptr<void>)>;
static void createCallback(void *arg);
@@ -114,7 +117,7 @@ class Thread final: public UnderlyingType<Thread, uv_thread_t> {
* seen as a global variable that is only visible to a particular thread and not
* the whole program.
*/
-class ThreadLocalStorage final: public UnderlyingType<ThreadLocalStorage, uv_key_t> {
+class UVW_EXTERN ThreadLocalStorage final: public UnderlyingType<ThreadLocalStorage, uv_key_t> {
public:
explicit ThreadLocalStorage(ConstructorAccess ca, std::shared_ptr<Loop> ref) noexcept;
@@ -148,7 +151,7 @@ class ThreadLocalStorage final: public UnderlyingType<ThreadLocalStorage, uv_key
* Runs a function once and only once. Concurrent calls to `once` will block all
* callers except one (it’s unspecified which one).
*/
-class Once final: public UnderlyingType<Once, uv_once_t> {
+class UVW_EXTERN Once final: public UnderlyingType<Once, uv_once_t> {
static uv_once_t* guard() noexcept;
public:
@@ -181,7 +184,7 @@ class Once final: public UnderlyingType<Once, uv_once_t> {
* * An option boolean that specifies if the mutex is a recursive one. The
* default value is false, the mutex isn't recursive.
*/
-class Mutex final: public UnderlyingType<Mutex, uv_mutex_t> {
+class UVW_EXTERN Mutex final: public UnderlyingType<Mutex, uv_mutex_t> {
friend class Condition;
public:
@@ -210,7 +213,7 @@ class Mutex final: public UnderlyingType<Mutex, uv_mutex_t> {
/**
* @brief The RWLock wrapper.
*/
-class RWLock final: public UnderlyingType<RWLock, uv_rwlock_t> {
+class UVW_EXTERN RWLock final: public UnderlyingType<RWLock, uv_rwlock_t> {
public:
explicit RWLock(ConstructorAccess ca, std::shared_ptr<Loop> ref) noexcept;
@@ -257,7 +260,7 @@ class RWLock final: public UnderlyingType<RWLock, uv_rwlock_t> {
*
* * An unsigned integer that specifies the initial value for the semaphore.
*/
-class Semaphore final: public UnderlyingType<Semaphore, uv_sem_t> {
+class UVW_EXTERN Semaphore final: public UnderlyingType<Semaphore, uv_sem_t> {
public:
explicit Semaphore(ConstructorAccess ca, std::shared_ptr<Loop> ref, unsigned int value) noexcept;
@@ -284,7 +287,7 @@ class Semaphore final: public UnderlyingType<Semaphore, uv_sem_t> {
/**
* @brief The Condition wrapper.
*/
-class Condition final: public UnderlyingType<Condition, uv_cond_t> {
+class UVW_EXTERN Condition final: public UnderlyingType<Condition, uv_cond_t> {
public:
explicit Condition(ConstructorAccess ca, std::shared_ptr<Loop> ref) noexcept;
@@ -344,7 +347,7 @@ class Condition final: public UnderlyingType<Condition, uv_cond_t> {
* `wait` before any of them successfully return from the call. The value
* specified must be greater than zero.
*/
-class Barrier final: public UnderlyingType<Barrier, uv_barrier_t> {
+class UVW_EXTERN Barrier final: public UnderlyingType<Barrier, uv_barrier_t> {
public:
explicit Barrier(ConstructorAccess ca, std::shared_ptr<Loop> ref, unsigned int count) noexcept;
@@ -365,4 +368,6 @@ class Barrier final: public UnderlyingType<Barrier, uv_barrier_t> {
#include "thread.cpp"
#endif
+UVW_MSVC_WARNING_POP();
+
#endif // UVW_THREAD_INCLUDE_H
diff --git a/src/uvw/timer.h b/src/uvw/timer.h
index b1fbb43..443de0e 100644
--- a/src/uvw/timer.h
+++ b/src/uvw/timer.h
@@ -6,6 +6,9 @@
#include <uv.h>
#include "handle.hpp"
#include "loop.h"
+#include "config.h"
+
+UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
namespace uvw {
@@ -16,7 +19,7 @@ namespace uvw {
*
* It will be emitted by TimerHandle according with its functionalities.
*/
-struct TimerEvent {};
+struct UVW_EXTERN TimerEvent {};
/**
@@ -26,7 +29,7 @@ struct TimerEvent {};
*
* To create a `TimerHandle` through a `Loop`, no arguments are required.
*/
-class TimerHandle final: public Handle<TimerHandle, uv_timer_t> {
+class UVW_EXTERN TimerHandle final: public Handle<TimerHandle, uv_timer_t> {
static void startCallback(uv_timer_t *handle);
public:
@@ -104,4 +107,6 @@ class TimerHandle final: public Handle<TimerHandle, uv_timer_t> {
#include "timer.cpp"
#endif
+UVW_MSVC_WARNING_POP();
+
#endif // UVW_TIMER_INCLUDE_H
diff --git a/src/uvw/tty.h b/src/uvw/tty.h
index bbfb1ff..9b283cd 100644
--- a/src/uvw/tty.h
+++ b/src/uvw/tty.h
@@ -7,6 +7,9 @@
#include <uv.h>
#include "stream.h"
#include "util.h"
+#include "config.h"
+
+UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
namespace uvw {
@@ -15,7 +18,7 @@ namespace uvw {
namespace details {
-struct ResetModeMemo {
+struct UVW_EXTERN ResetModeMemo {
~ResetModeMemo();
};
@@ -54,7 +57,7 @@ enum class UVTTYVTermStateT: std::underlying_type_t<uv_tty_vtermstate_t> {
* [documentation](http://docs.libuv.org/en/v1.x/tty.html#c.uv_tty_init)
* for further details.
*/
-class TTYHandle final: public StreamHandle<TTYHandle, uv_tty_t> {
+class UVW_EXTERN TTYHandle final: public StreamHandle<TTYHandle, uv_tty_t> {
static std::shared_ptr<details::ResetModeMemo> resetModeMemo();
public:
@@ -152,4 +155,6 @@ class TTYHandle final: public StreamHandle<TTYHandle, uv_tty_t> {
#include "tty.cpp"
#endif
+UVW_MSVC_WARNING_POP();
+
#endif // UVW_TTY_INCLUDE_H
diff --git a/src/uvw/type_factory/type_factory.cpp b/src/uvw/type_factory/type_factory.cpp
new file mode 100644
index 0000000..f0df4f9
--- /dev/null
+++ b/src/uvw/type_factory/type_factory.cpp
@@ -0,0 +1,264 @@
+#include "type_factory.h"
+
+#include <uvw.hpp>
+
+namespace uvw::details {
+ template<typename T>
+ std::size_t type_factory<T>::next_type() noexcept {
+ static std::size_t counter = 0;
+ return counter++;
+ }
+
+ template<typename T>
+ template<typename>
+ std::size_t type_factory<T>::event_type() noexcept {
+ static std::size_t value = next_type();
+ return value;
+ }
+}
+
+
+namespace uvw {
+ template std::size_t details::type_factory<IdleHandle>::event_type<ErrorEvent>() noexcept;
+
+ template std::size_t details::type_factory<IdleHandle>::event_type<CloseEvent>() noexcept;
+
+ template std::size_t details::type_factory<IdleHandle>::event_type<IdleEvent>() noexcept;
+
+ template std::size_t details::type_factory<AsyncHandle>::event_type<AsyncEvent>() noexcept;
+
+ template std::size_t details::type_factory<AsyncHandle>::event_type<ErrorEvent>() noexcept;
+
+ template std::size_t details::type_factory<WorkReq>::event_type<WorkEvent>() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 1> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 2> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 3> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 4> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 5> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 6> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 7> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 8> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 9> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 10> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 11> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 12> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 13> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 14> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 15> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 16> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 17> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 18> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 19> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 20> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 21> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 22> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 23> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 24> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 25> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 26> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 27> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 28> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 29> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 30> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 31> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 32> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 33> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 34> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 35> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 36> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 37> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 38> >() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<FsEvent<(details::UVFsType) 39> >() noexcept;
+
+
+ template std::size_t details::type_factory<details::ShutdownReq>::event_type<ErrorEvent>() noexcept;
+
+ template std::size_t details::type_factory<FileReq>::event_type<FsEvent<(details::UVFsType) 11> >() noexcept;
+
+ template std::size_t details::type_factory<GetNameInfoReq>::event_type<NameInfoEvent>() noexcept;
+
+ template std::size_t details::type_factory<TimerHandle>::event_type<TimerEvent>() noexcept;
+
+ template std::size_t details::type_factory<CheckHandle>::event_type<ErrorEvent>() noexcept;
+
+ template std::size_t details::type_factory<FsReq>::event_type<ErrorEvent>() noexcept;
+
+ template std::size_t details::type_factory<FileReq>::event_type<FsEvent<(details::UVFsType) 27> >() noexcept;
+
+ template std::size_t details::type_factory<details::SendReq>::event_type<ErrorEvent>() noexcept;
+
+ template std::size_t details::type_factory<FileReq>::event_type<FsEvent<(details::UVFsType) 9> >() noexcept;
+
+ template std::size_t details::type_factory<TCPHandle>::event_type<CloseEvent>() noexcept;
+
+ template std::size_t details::type_factory<ProcessHandle>::event_type<ExitEvent>() noexcept;
+
+ template std::size_t details::type_factory<FileReq>::event_type<ErrorEvent>() noexcept;
+
+ template std::size_t details::type_factory<PrepareHandle>::event_type<PrepareEvent>() noexcept;
+
+ template std::size_t details::type_factory<TCPHandle>::event_type<ConnectEvent>() noexcept;
+
+ template std::size_t details::type_factory<FsEventHandle>::event_type<ErrorEvent>() noexcept;
+
+ template std::size_t details::type_factory<FileReq>::event_type<FsEvent<(details::UVFsType) 15> >() noexcept;
+
+ template std::size_t details::type_factory<FsEventHandle>::event_type<FsEventEvent>() noexcept;
+
+ template std::size_t details::type_factory<TimerHandle>::event_type<ErrorEvent>() noexcept;
+
+ template std::size_t details::type_factory<TCPHandle>::event_type<ErrorEvent>() noexcept;
+
+ template std::size_t details::type_factory<GetNameInfoReq>::event_type<ErrorEvent>() noexcept;
+
+ template std::size_t details::type_factory<PrepareHandle>::event_type<ErrorEvent>() noexcept;
+
+ template std::size_t details::type_factory<WorkReq>::event_type<ErrorEvent>() noexcept;
+
+ template std::size_t details::type_factory<PollHandle>::event_type<PollEvent>() noexcept;
+
+ template std::size_t details::type_factory<PollHandle>::event_type<CloseEvent>() noexcept;
+
+ template std::size_t details::type_factory<SignalHandle>::event_type<SignalEvent>() noexcept;
+
+ template std::size_t details::type_factory<PipeHandle>::event_type<ConnectEvent>() noexcept;
+
+ template std::size_t details::type_factory<details::ShutdownReq>::event_type<ShutdownEvent>() noexcept;
+
+ template std::size_t details::type_factory<FileReq>::event_type<FsEvent<(details::UVFsType) 5> >() noexcept;
+
+ template std::size_t details::type_factory<TTYHandle>::event_type<CloseEvent>() noexcept;
+
+ template std::size_t details::type_factory<UDPHandle>::event_type<CloseEvent>() noexcept;
+
+ template std::size_t details::type_factory<Loop>::event_type<ErrorEvent>() noexcept;
+
+ template std::size_t details::type_factory<UDPHandle>::event_type<SendEvent>() noexcept;
+
+ template std::size_t details::type_factory<PipeHandle>::event_type<CloseEvent>() noexcept;
+
+ template std::size_t details::type_factory<FsPollHandle>::event_type<ErrorEvent>() noexcept;
+
+ template std::size_t details::type_factory<GetAddrInfoReq>::event_type<AddrInfoEvent>() noexcept;
+
+ template std::size_t details::type_factory<details::ConnectReq>::event_type<ConnectEvent>() noexcept;
+
+ template std::size_t details::type_factory<UDPHandle>::event_type<UDPDataEvent>() noexcept;
+
+ template std::size_t details::type_factory<details::ConnectReq>::event_type<ErrorEvent>() noexcept;
+
+ template std::size_t details::type_factory<FileReq>::event_type<FsEvent<(details::UVFsType) 14> >() noexcept;
+
+ template std::size_t details::type_factory<FsPollHandle>::event_type<FsPollEvent>() noexcept;
+
+ template std::size_t details::type_factory<FileReq>::event_type<FsEvent<(details::UVFsType) 16> >() noexcept;
+
+ template std::size_t details::type_factory<GetAddrInfoReq>::event_type<ErrorEvent>() noexcept;
+
+ template std::size_t details::type_factory<UDPHandle>::event_type<ErrorEvent>() noexcept;
+
+ template std::size_t details::type_factory<FileReq>::event_type<FsEvent<(details::UVFsType) 1> >() noexcept;
+
+ template std::size_t details::type_factory<details::SendReq>::event_type<SendEvent>() noexcept;
+
+ template std::size_t details::type_factory<SignalHandle>::event_type<ErrorEvent>() noexcept;
+
+ template std::size_t details::type_factory<FileReq>::event_type<FsEvent<(details::UVFsType) 2> >() noexcept;
+
+ template std::size_t details::type_factory<FileReq>::event_type<FsEvent<(details::UVFsType) 3> >() noexcept;
+
+ template std::size_t details::type_factory<FileReq>::event_type<FsEvent<(details::UVFsType) 8> >() noexcept;
+
+ template std::size_t details::type_factory<FileReq>::event_type<FsEvent<(details::UVFsType) 4> >() noexcept;
+
+ template std::size_t details::type_factory<ProcessHandle>::event_type<CloseEvent>() noexcept;
+
+ template std::size_t details::type_factory<ProcessHandle>::event_type<ErrorEvent>() noexcept;
+
+ template std::size_t details::type_factory<TTYHandle>::event_type<ErrorEvent>() noexcept;
+
+ template std::size_t details::type_factory<PollHandle>::event_type<ErrorEvent>() noexcept;
+
+ template std::size_t details::type_factory<PipeHandle>::event_type<ErrorEvent>() noexcept;
+
+ template std::size_t details::type_factory<CheckHandle>::event_type<CheckEvent>() noexcept;
+
+ template std::size_t details::type_factory<CheckHandle>::event_type<CloseEvent>() noexcept;
+ template std::size_t details::type_factory<TimerHandle>::event_type<CloseEvent>() noexcept;
+
+ template std::size_t details::type_factory<AsyncHandle>::event_type<CloseEvent>() noexcept;
+
+ template std::size_t details::type_factory<PrepareHandle>::event_type<CloseEvent>() noexcept;
+
+ template std::size_t details::type_factory<FsEventHandle>::event_type<CloseEvent>() noexcept;
+ template std::size_t details::type_factory<FsPollHandle>::event_type<CloseEvent>() noexcept;
+
+ template std::size_t details::type_factory<TCPHandle>::event_type<WriteEvent>() noexcept;
+ template std::size_t details::type_factory<TCPHandle>::event_type<EndEvent>() noexcept;
+ template std::size_t details::type_factory<TCPHandle>::event_type<DataEvent>() noexcept;
+ template std::size_t details::type_factory<TCPHandle>::event_type<ListenEvent>() noexcept;
+ template std::size_t details::type_factory<TCPHandle>::event_type<ShutdownEvent>() noexcept;
+
+ template std::size_t details::type_factory<TTYHandle>::event_type<WriteEvent>() noexcept;
+
+ template std::size_t details::type_factory<uvw::PipeHandle>::event_type<WriteEvent>() noexcept;
+ template std::size_t details::type_factory<uvw::PipeHandle>::event_type<EndEvent>() noexcept;
+ template std::size_t details::type_factory<uvw::PipeHandle>::event_type<DataEvent>() noexcept;
+ template std::size_t details::type_factory<uvw::PipeHandle>::event_type<ListenEvent>() noexcept;
+ template std::size_t details::type_factory<uvw::PipeHandle>::event_type<ShutdownEvent>() noexcept;
+
+ template std::size_t details::type_factory<SignalHandle>::event_type<CheckEvent>() noexcept;
+ template std::size_t details::type_factory<SignalHandle>::event_type<CloseEvent>() noexcept;
+
+ template std::size_t details::type_factory<WriteReq<std::default_delete<char []> > >::event_type<ErrorEvent>() noexcept;
+ template std::size_t details::type_factory<WriteReq<std::default_delete<char []> > >::event_type<WriteEvent>() noexcept;
+
+ template std::size_t details::type_factory<WriteReq<void (*)(char*) > >::event_type<ErrorEvent>() noexcept;
+ template std::size_t details::type_factory<WriteReq<void (*)(char*) > >::event_type<WriteEvent>() noexcept;
+
+ template std::size_t details::type_factory<FakeHandle>::event_type<CloseEvent>() noexcept;
+ template std::size_t details::type_factory<FakeHandle>::event_type<ErrorEvent>() noexcept;
+
+ template std::size_t details::type_factory<TestEmitter>::event_type<FakeEvent>() noexcept;
+ template std::size_t details::type_factory<TestEmitter>::event_type<ErrorEvent>() noexcept;
+
+}
diff --git a/src/uvw/type_factory/type_factory.h b/src/uvw/type_factory/type_factory.h
new file mode 100644
index 0000000..32b20a0
--- /dev/null
+++ b/src/uvw/type_factory/type_factory.h
@@ -0,0 +1,18 @@
+#ifndef UVW_TYPE_FACTORY_H
+#define UVW_TYPE_FACTORY_H
+
+#include <uvw/config.h>
+#include <cstddef>
+
+namespace uvw::details {
+ template<typename T>
+ struct UVW_EXTERN type_factory {
+ template<typename>
+ static std::size_t event_type() noexcept;
+
+ static std::size_t next_type() noexcept;
+ };
+}
+
+
+#endif //UVW_TYPE_FACTORY_H
diff --git a/src/uvw/udp.h b/src/uvw/udp.h
index 68769a8..3251b02 100644
--- a/src/uvw/udp.h
+++ b/src/uvw/udp.h
@@ -11,6 +11,9 @@
#include "request.hpp"
#include "handle.hpp"
#include "util.h"
+#include "config.h"
+
+UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
namespace uvw {
@@ -21,7 +24,7 @@ namespace uvw {
*
* It will be emitted by UDPHandle according with its functionalities.
*/
-struct SendEvent {};
+struct UVW_EXTERN SendEvent {};
/**
@@ -29,7 +32,7 @@ struct SendEvent {};
*
* It will be emitted by UDPHandle according with its functionalities.
*/
-struct UDPDataEvent {
+struct UVW_EXTERN UDPDataEvent {
explicit UDPDataEvent(Addr sndr, std::unique_ptr<const char[]> buf, std::size_t len, bool part) noexcept;
std::unique_ptr<const char[]> data; /*!< A bunch of data read on the stream. */
@@ -57,7 +60,7 @@ enum class UVMembership: std::underlying_type_t<uv_membership> {
};
-class SendReq final: public Request<SendReq, uv_udp_send_t> {
+class UVW_EXTERN SendReq final: public Request<SendReq, uv_udp_send_t> {
public:
using Deleter = void(*)(char *);
@@ -90,7 +93,7 @@ class SendReq final: public Request<SendReq, uv_udp_send_t> {
* [documentation](http://docs.libuv.org/en/v1.x/udp.html#c.uv_udp_init_ex)
* for further details.
*/
-class UDPHandle final: public Handle<UDPHandle, uv_udp_t> {
+class UVW_EXTERN UDPHandle final: public Handle<UDPHandle, uv_udp_t> {
template<typename I>
static void recvCallback(uv_udp_t *handle, ssize_t nread, const uv_buf_t *buf, const sockaddr *addr, unsigned flags) {
const typename details::IpTraits<I>::Type *aptr = reinterpret_cast<const typename details::IpTraits<I>::Type *>(addr);
@@ -578,62 +581,62 @@ class UDPHandle final: public Handle<UDPHandle, uv_udp_t> {
// (extern) explicit instantiations
-extern template void UDPHandle::connect<IPv4>(std::string, unsigned int);
-extern template void UDPHandle::connect<IPv6>(std::string, unsigned int);
+extern template UVW_EXTERN void UDPHandle::connect<IPv4>(std::string, unsigned int);
+extern template UVW_EXTERN void UDPHandle::connect<IPv6>(std::string, unsigned int);
-extern template void UDPHandle::connect<IPv4>(Addr);
-extern template void UDPHandle::connect<IPv6>(Addr);
+extern template UVW_EXTERN void UDPHandle::connect<IPv4>(Addr);
+extern template UVW_EXTERN void UDPHandle::connect<IPv6>(Addr);
-extern template Addr UDPHandle::peer<IPv4>() const noexcept;
-extern template Addr UDPHandle::peer<IPv6>() const noexcept;
+extern template UVW_EXTERN Addr UDPHandle::peer<IPv4>() const noexcept;
+extern template UVW_EXTERN Addr UDPHandle::peer<IPv6>() const noexcept;
-extern template void UDPHandle::bind<IPv4>(std::string, unsigned int, Flags<Bind>);
-extern template void UDPHandle::bind<IPv6>(std::string, unsigned int, Flags<Bind>);
+extern template UVW_EXTERN void UDPHandle::bind<IPv4>(std::string, unsigned int, Flags<Bind>);
+extern template UVW_EXTERN void UDPHandle::bind<IPv6>(std::string, unsigned int, Flags<Bind>);
-extern template void UDPHandle::bind<IPv4>(Addr, Flags<Bind>);
-extern template void UDPHandle::bind<IPv6>(Addr, Flags<Bind>);
+extern template UVW_EXTERN void UDPHandle::bind<IPv4>(Addr, Flags<Bind>);
+extern template UVW_EXTERN void UDPHandle::bind<IPv6>(Addr, Flags<Bind>);
-extern template Addr UDPHandle::sock<IPv4>() const noexcept;
-extern template Addr UDPHandle::sock<IPv6>() const noexcept;
+extern template UVW_EXTERN Addr UDPHandle::sock<IPv4>() const noexcept;
+extern template UVW_EXTERN Addr UDPHandle::sock<IPv6>() const noexcept;
-extern template bool UDPHandle::multicastMembership<IPv4>(std::string, std::string, Membership);
-extern template bool UDPHandle::multicastMembership<IPv6>(std::string, std::string, Membership);
+extern template UVW_EXTERN bool UDPHandle::multicastMembership<IPv4>(std::string, std::string, Membership);
+extern template UVW_EXTERN bool UDPHandle::multicastMembership<IPv6>(std::string, std::string, Membership);
-extern template bool UDPHandle::multicastInterface<IPv4>(std::string);
-extern template bool UDPHandle::multicastInterface<IPv6>(std::string);
+extern template UVW_EXTERN bool UDPHandle::multicastInterface<IPv4>(std::string);
+extern template UVW_EXTERN bool UDPHandle::multicastInterface<IPv6>(std::string);
-extern template void UDPHandle::send<IPv4>(std::string, unsigned int, std::unique_ptr<char[]>, unsigned int);
-extern template void UDPHandle::send<IPv6>(std::string, unsigned int, std::unique_ptr<char[]>, unsigned int);
+extern template UVW_EXTERN void UDPHandle::send<IPv4>(std::string, unsigned int, std::unique_ptr<char[]>, unsigned int);
+extern template UVW_EXTERN void UDPHandle::send<IPv6>(std::string, unsigned int, std::unique_ptr<char[]>, unsigned int);
-extern template void UDPHandle::send<IPv4>(Addr, std::unique_ptr<char[]>, unsigned int);
-extern template void UDPHandle::send<IPv6>(Addr, std::unique_ptr<char[]>, unsigned int);
+extern template UVW_EXTERN void UDPHandle::send<IPv4>(Addr, std::unique_ptr<char[]>, unsigned int);
+extern template UVW_EXTERN void UDPHandle::send<IPv6>(Addr, std::unique_ptr<char[]>, unsigned int);
-extern template void UDPHandle::send<IPv4>(std::string, unsigned int, char *, unsigned int);
-extern template void UDPHandle::send<IPv6>(std::string, unsigned int, char *, unsigned int);
+extern template UVW_EXTERN void UDPHandle::send<IPv4>(std::string, unsigned int, char *, unsigned int);
+extern template UVW_EXTERN void UDPHandle::send<IPv6>(std::string, unsigned int, char *, unsigned int);
-extern template void UDPHandle::send<IPv4>(Addr, char *, unsigned int);
-extern template void UDPHandle::send<IPv6>(Addr, char *, unsigned int);
+extern template UVW_EXTERN void UDPHandle::send<IPv4>(Addr, char *, unsigned int);
+extern template UVW_EXTERN void UDPHandle::send<IPv6>(Addr, char *, unsigned int);
-extern template int UDPHandle::trySend<IPv4>(const sockaddr &, std::unique_ptr<char[]>, unsigned int);
-extern template int UDPHandle::trySend<IPv6>(const sockaddr &, std::unique_ptr<char[]>, unsigned int);
+extern template UVW_EXTERN int UDPHandle::trySend<IPv4>(const sockaddr &, std::unique_ptr<char[]>, unsigned int);
+extern template UVW_EXTERN int UDPHandle::trySend<IPv6>(const sockaddr &, std::unique_ptr<char[]>, unsigned int);
-extern template int UDPHandle::trySend<IPv4>(std::string, unsigned int, std::unique_ptr<char[]>, unsigned int);
-extern template int UDPHandle::trySend<IPv6>(std::string, unsigned int, std::unique_ptr<char[]>, unsigned int);
+extern template UVW_EXTERN int UDPHandle::trySend<IPv4>(std::string, unsigned int, std::unique_ptr<char[]>, unsigned int);
+extern template UVW_EXTERN int UDPHandle::trySend<IPv6>(std::string, unsigned int, std::unique_ptr<char[]>, unsigned int);
-extern template int UDPHandle::trySend<IPv4>(Addr, std::unique_ptr<char[]>, unsigned int);
-extern template int UDPHandle::trySend<IPv6>(Addr, std::unique_ptr<char[]>, unsigned int);
+extern template UVW_EXTERN int UDPHandle::trySend<IPv4>(Addr, std::unique_ptr<char[]>, unsigned int);
+extern template UVW_EXTERN int UDPHandle::trySend<IPv6>(Addr, std::unique_ptr<char[]>, unsigned int);
-extern template int UDPHandle::trySend<IPv4>(const sockaddr &, char *, unsigned int);
-extern template int UDPHandle::trySend<IPv6>(const sockaddr &, char *, unsigned int);
+extern template UVW_EXTERN int UDPHandle::trySend<IPv4>(const sockaddr &, char *, unsigned int);
+extern template UVW_EXTERN int UDPHandle::trySend<IPv6>(const sockaddr &, char *, unsigned int);
-extern template int UDPHandle::trySend<IPv4>(std::string, unsigned int, char *, unsigned int);
-extern template int UDPHandle::trySend<IPv6>(std::string, unsigned int, char *, unsigned int);
+extern template UVW_EXTERN int UDPHandle::trySend<IPv4>(std::string, unsigned int, char *, unsigned int);
+extern template UVW_EXTERN int UDPHandle::trySend<IPv6>(std::string, unsigned int, char *, unsigned int);
-extern template int UDPHandle::trySend<IPv4>(Addr, char *, unsigned int);
-extern template int UDPHandle::trySend<IPv6>(Addr, char *, unsigned int);
+extern template UVW_EXTERN int UDPHandle::trySend<IPv4>(Addr, char *, unsigned int);
+extern template UVW_EXTERN int UDPHandle::trySend<IPv6>(Addr, char *, unsigned int);
-extern template void UDPHandle::recv<IPv4>();
-extern template void UDPHandle::recv<IPv6>();
+extern template UVW_EXTERN void UDPHandle::recv<IPv4>();
+extern template UVW_EXTERN void UDPHandle::recv<IPv6>();
}
@@ -642,4 +645,6 @@ extern template void UDPHandle::recv<IPv6>();
#include "udp.cpp"
#endif
+UVW_MSVC_WARNING_POP();
+
#endif // UVW_UDP_INCLUDE_H
diff --git a/src/uvw/underlying_type.hpp b/src/uvw/underlying_type.hpp
index 06c4a57..78cd5d7 100644
--- a/src/uvw/underlying_type.hpp
+++ b/src/uvw/underlying_type.hpp
@@ -6,6 +6,9 @@
#include <type_traits>
#include <utility>
#include "loop.h"
+#include "config.h"
+
+UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
namespace uvw {
@@ -116,4 +119,6 @@ class UnderlyingType {
}
+UVW_MSVC_WARNING_POP();
+
#endif // UVW_UNDERLYING_TYPE_INCLUDE_H
diff --git a/src/uvw/util.cpp b/src/uvw/util.cpp
index 95ef325..2f8a3a2 100644
--- a/src/uvw/util.cpp
+++ b/src/uvw/util.cpp
@@ -69,6 +69,10 @@ UVW_INLINE std::string UtsName::machine() const noexcept {
return utsname ? utsname->machine : "";
}
+const details::IpTraits<IPv4>::AddrFuncType details::IpTraits<IPv4>::addrFunc = &uv_ip4_addr;
+const details::IpTraits<IPv4>::NameFuncType details::IpTraits<IPv4>::nameFunc = &uv_ip4_name;
+const details::IpTraits<IPv6>::AddrFuncType details::IpTraits<IPv6>::addrFunc = &uv_ip6_addr;
+const details::IpTraits<IPv6>::NameFuncType details::IpTraits<IPv6>::nameFunc = &uv_ip6_name;
UVW_INLINE PidType Utilities::OS::pid() noexcept {
return uv_os_getpid();
diff --git a/src/uvw/util.h b/src/uvw/util.h
index 4227137..93c7b34 100644
--- a/src/uvw/util.h
+++ b/src/uvw/util.h
@@ -11,6 +11,9 @@
#include <memory>
#include <array>
#include <uv.h>
+#include "config.h"
+
+UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
namespace uvw {
@@ -177,7 +180,7 @@ class Flags final {
/**
* @brief Windows size representation.
*/
-struct WinSize {
+struct UVW_EXTERN WinSize {
int width; /*!< The _width_ of the given window. */
int height; /*!< The _height_ of the given window. */
};
@@ -214,7 +217,7 @@ using RUsage = uv_rusage_t; /*!< Library equivalent for uv_rusage_t. */
*
* \sa Utilities::passwd
*/
-struct Passwd {
+struct UVW_EXTERN Passwd {
Passwd(std::shared_ptr<uv_passwd_t> pwd);
/**
@@ -267,7 +270,7 @@ struct Passwd {
*
* \sa Utilities::uname
*/
-struct UtsName {
+struct UVW_EXTERN UtsName {
UtsName(std::shared_ptr<uv_utsname_t> utsname);
/**
@@ -304,7 +307,7 @@ struct UtsName {
*
* To be used as template parameter to switch between IPv4 and IPv6.
*/
-struct IPv4 {};
+struct UVW_EXTERN IPv4 {};
/**
@@ -312,13 +315,13 @@ struct IPv4 {};
*
* To be used as template parameter to switch between IPv4 and IPv6.
*/
-struct IPv6 {};
+struct UVW_EXTERN IPv6 {};
/**
* @brief Address representation.
*/
-struct Addr {
+struct UVW_EXTERN Addr {
std::string ip; /*!< Either an IPv4 or an IPv6. */
unsigned int port; /*!< A valid service identifier. */
};
@@ -327,7 +330,7 @@ struct Addr {
/**
* \brief CPU information.
*/
-struct CPUInfo {
+struct UVW_EXTERN CPUInfo {
using CPUTime = decltype(uv_cpu_info_t::cpu_times);
std::string model; /*!< The model of the CPU. */
@@ -346,7 +349,7 @@ struct CPUInfo {
/**
* \brief Interface address.
*/
-struct InterfaceAddress {
+struct UVW_EXTERN InterfaceAddress {
std::string name; /*!< The name of the interface (as an example _eth0_). */
char physical[6]; /*!< The physical address. */
bool internal; /*!< True if it is an internal interface (as an example _loopback_), false otherwise. */
@@ -364,14 +367,13 @@ static constexpr std::size_t DEFAULT_SIZE = 128;
template<typename>
struct IpTraits;
-
template<>
struct IpTraits<IPv4> {
using Type = sockaddr_in;
- using AddrFuncType = int(*)(const char *, int, Type *);
- using NameFuncType = int(*)(const Type *, char *, std::size_t);
- static constexpr AddrFuncType addrFunc = &uv_ip4_addr;
- static constexpr NameFuncType nameFunc = &uv_ip4_name;
+ using AddrFuncType = int (*)(const char*, int, Type*);
+ using NameFuncType = int (*)(const Type*, char*, std::size_t);
+ static UVW_EXTERN const AddrFuncType addrFunc;
+ static UVW_EXTERN const NameFuncType nameFunc;
static constexpr auto sinPort(const Type *addr) { return addr->sin_port; }
};
@@ -381,8 +383,8 @@ struct IpTraits<IPv6> {
using Type = sockaddr_in6;
using AddrFuncType = int(*)(const char *, int, Type *);
using NameFuncType = int(*)(const Type *, char *, std::size_t);
- static constexpr AddrFuncType addrFunc = &uv_ip6_addr;
- static constexpr NameFuncType nameFunc = &uv_ip6_name;
+ static UVW_EXTERN const AddrFuncType addrFunc;
+ static UVW_EXTERN const NameFuncType nameFunc;
static constexpr auto sinPort(const Type *addr) { return addr->sin6_port; }
};
@@ -450,7 +452,7 @@ std::string tryRead(F &&f, Args&&... args) noexcept {
*
* Miscellaneous functions that don’t really belong to any other class.
*/
-struct Utilities {
+struct UVW_EXTERN Utilities {
using MallocFuncType = void*(*)(size_t);
using ReallocFuncType = void*(*)(void*, size_t);
using CallocFuncType = void*(*)(size_t, size_t);
@@ -459,7 +461,7 @@ struct Utilities {
/**
* @brief OS dedicated utilities.
*/
- struct OS {
+ struct UVW_EXTERN OS {
/**
* @brief Returns the current process id.
*
@@ -829,4 +831,6 @@ struct Utilities {
#include "util.cpp"
#endif
+UVW_MSVC_WARNING_POP();
+
#endif // UVW_UTIL_INCLUDE_H
diff --git a/src/uvw/work.h b/src/uvw/work.h
index 00cc86f..f5b9c3c 100644
--- a/src/uvw/work.h
+++ b/src/uvw/work.h
@@ -7,6 +7,9 @@
#include <uv.h>
#include "request.hpp"
#include "loop.h"
+#include "config.h"
+
+UVW_MSVC_WARNING_PUSH_DISABLE_DLLINTERFACE();
namespace uvw {
@@ -17,7 +20,7 @@ namespace uvw {
*
* It will be emitted by WorkReq according with its functionalities.
*/
-struct WorkEvent {};
+struct UVW_EXTERN WorkEvent {};
/**
@@ -34,7 +37,7 @@ struct WorkEvent {};
* [documentation](http://docs.libuv.org/en/v1.x/threadpool.html)
* for further details.
*/
-class WorkReq final: public Request<WorkReq, uv_work_t> {
+class UVW_EXTERN WorkReq final: public Request<WorkReq, uv_work_t> {
using InternalTask = std::function<void(void)>;
static void workCallback(uv_work_t *req);
@@ -65,4 +68,6 @@ class WorkReq final: public Request<WorkReq, uv_work_t> {
#include "work.cpp"
#endif
+UVW_MSVC_WARNING_POP();
+
#endif // UVW_WORK_INCLUDE_H
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 8d0b3e7..5f89f70 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -47,7 +47,7 @@ function(ADD_UVW_TEST TEST_NAME TEST_SOURCE)
PRIVATE
$<$<TARGET_EXISTS:uvw::uvw>:uvw::uvw>
$<$<TARGET_EXISTS:uvw::uvw>:uv::uv-static>
- $<$<TARGET_EXISTS:uvw::uvw-static>:uvw::uvw-static>
+ $<$<TARGET_EXISTS:uvw::uvw-shared>:uvw::uvw-shared>
GTest::Main
Threads::Threads
${LIBRT}
diff --git a/test/main.cpp b/test/main.cpp
index dde20ac..e29aab5 100644
--- a/test/main.cpp
+++ b/test/main.cpp
@@ -1,93 +1,93 @@
-#include <uvw.hpp>
-#include <cassert>
-#include <iostream>
-#include <memory>
-#include <chrono>
-
-
-void listen(uvw::Loop &loop) {
- std::shared_ptr<uvw::TCPHandle> tcp = loop.resource<uvw::TCPHandle>();
- tcp->on<uvw::ErrorEvent>([](const uvw::ErrorEvent &, uvw::TCPHandle &) { assert(false); });
-
- tcp->once<uvw::ListenEvent>([](const uvw::ListenEvent &, uvw::TCPHandle &srv) {
- std::cout << "listen" << std::endl;
-
- std::shared_ptr<uvw::TCPHandle> client = srv.loop().resource<uvw::TCPHandle>();
- client->on<uvw::ErrorEvent>([](const uvw::ErrorEvent &, uvw::TCPHandle &) { assert(false); });
-
- client->on<uvw::CloseEvent>([ptr = srv.shared_from_this()](const uvw::CloseEvent &, uvw::TCPHandle &) {
- std::cout << "close" << std::endl;
- ptr->close();
- });
-
- srv.accept(*client);
-
- uvw::Addr local = srv.sock();
- std::cout << "local: " << local.ip << " " << local.port << std::endl;
-
- uvw::Addr remote = client->peer();
- std::cout << "remote: " << remote.ip << " " << remote.port << std::endl;
-
- client->on<uvw::DataEvent>([](const uvw::DataEvent &event, uvw::TCPHandle &) {
- std::cout.write(event.data.get(), event.length) << std::endl;
- std::cout << "data length: " << event.length << std::endl;
- });
-
- client->on<uvw::EndEvent>([](const uvw::EndEvent &, uvw::TCPHandle &handle) {
- std::cout << "end" << std::endl;
- int count = 0;
- handle.loop().walk([&count](uvw::BaseHandle &) { ++count; });
- std::cout << "still alive: " << count << " handles" << std::endl;
- handle.close();
- });
-
- client->read();
- });
-
- tcp->once<uvw::CloseEvent>([](const uvw::CloseEvent &, uvw::TCPHandle &) {
- std::cout << "close" << std::endl;
- });
-
- tcp->bind("127.0.0.1", 4242);
- tcp->listen();
-}
-
-
-void conn(uvw::Loop &loop) {
- auto tcp = loop.resource<uvw::TCPHandle>();
- tcp->on<uvw::ErrorEvent>([](const uvw::ErrorEvent &, uvw::TCPHandle &) { assert(false); });
-
- tcp->once<uvw::WriteEvent>([](const uvw::WriteEvent &, uvw::TCPHandle &handle) {
- std::cout << "write" << std::endl;
- handle.close();
- });
-
- tcp->once<uvw::ConnectEvent>([](const uvw::ConnectEvent &, uvw::TCPHandle &handle) {
- std::cout << "connect" << std::endl;
-
- auto dataTryWrite = std::unique_ptr<char[]>(new char[1]{ 'a' });
- int bw = handle.tryWrite(std::move(dataTryWrite), 1);
- std::cout << "written: " << ((int)bw) << std::endl;
-
- auto dataWrite = std::unique_ptr<char[]>(new char[2]{ 'b', 'c' });
- handle.write(std::move(dataWrite), 2);
- });
-
- tcp->once<uvw::CloseEvent>([](const uvw::CloseEvent &, uvw::TCPHandle &) {
- std::cout << "close" << std::endl;
- });
-
- tcp->connect("127.0.0.1", 4242);
-}
-
-void g() {
- auto loop = uvw::Loop::getDefault();
- listen(*loop);
- conn(*loop);
- loop->run();
- loop = nullptr;
-}
-
-int main() {
- g();
-}
+//#include <uvw.hpp>
+//#include <cassert>
+//#include <iostream>
+//#include <memory>
+//#include <chrono>
+//
+//
+//void listen(uvw::Loop &loop) {
+// std::shared_ptr<uvw::TCPHandle> tcp = loop.resource<uvw::TCPHandle>();
+// tcp->on<uvw::ErrorEvent>([](const uvw::ErrorEvent &, uvw::TCPHandle &) { assert(false); });
+//
+// tcp->once<uvw::ListenEvent>([](const uvw::ListenEvent &, uvw::TCPHandle &srv) {
+// std::cout << "listen" << std::endl;
+//
+// std::shared_ptr<uvw::TCPHandle> client = srv.loop().resource<uvw::TCPHandle>();
+// client->on<uvw::ErrorEvent>([](const uvw::ErrorEvent &, uvw::TCPHandle &) { assert(false); });
+//
+// client->on<uvw::CloseEvent>([ptr = srv.shared_from_this()](const uvw::CloseEvent &, uvw::TCPHandle &) {
+// std::cout << "close" << std::endl;
+// ptr->close();
+// });
+//
+// srv.accept(*client);
+//
+// uvw::Addr local = srv.sock();
+// std::cout << "local: " << local.ip << " " << local.port << std::endl;
+//
+// uvw::Addr remote = client->peer();
+// std::cout << "remote: " << remote.ip << " " << remote.port << std::endl;
+//
+// client->on<uvw::DataEvent>([](const uvw::DataEvent &event, uvw::TCPHandle &) {
+// std::cout.write(event.data.get(), event.length) << std::endl;
+// std::cout << "data length: " << event.length << std::endl;
+// });
+//
+// client->on<uvw::EndEvent>([](const uvw::EndEvent &, uvw::TCPHandle &handle) {
+// std::cout << "end" << std::endl;
+// int count = 0;
+// handle.loop().walk([&count](uvw::BaseHandle &) { ++count; });
+// std::cout << "still alive: " << count << " handles" << std::endl;
+// handle.close();
+// });
+//
+// client->read();
+// });
+//
+// tcp->once<uvw::CloseEvent>([](const uvw::CloseEvent &, uvw::TCPHandle &) {
+// std::cout << "close" << std::endl;
+// });
+//
+// tcp->bind("127.0.0.1", 4242);
+// tcp->listen();
+//}
+//
+//
+//void conn(uvw::Loop &loop) {
+// auto tcp = loop.resource<uvw::TCPHandle>();
+// tcp->on<uvw::ErrorEvent>([](const uvw::ErrorEvent &, uvw::TCPHandle &) { assert(false); });
+//
+// tcp->once<uvw::WriteEvent>([](const uvw::WriteEvent &, uvw::TCPHandle &handle) {
+// std::cout << "write" << std::endl;
+// handle.close();
+// });
+//
+// tcp->once<uvw::ConnectEvent>([](const uvw::ConnectEvent &, uvw::TCPHandle &handle) {
+// std::cout << "connect" << std::endl;
+//
+// auto dataTryWrite = std::unique_ptr<char[]>(new char[1]{ 'a' });
+// int bw = handle.tryWrite(std::move(dataTryWrite), 1);
+// std::cout << "written: " << ((int)bw) << std::endl;
+//
+// auto dataWrite = std::unique_ptr<char[]>(new char[2]{ 'b', 'c' });
+// handle.write(std::move(dataWrite), 2);
+// });
+//
+// tcp->once<uvw::CloseEvent>([](const uvw::CloseEvent &, uvw::TCPHandle &) {
+// std::cout << "close" << std::endl;
+// });
+//
+// tcp->connect("127.0.0.1", 4242);
+//}
+//
+//void g() {
+// auto loop = uvw::Loop::getDefault();
+// listen(*loop);
+// conn(*loop);
+// loop->run();
+// loop = nullptr;
+//}
+//
+//int main() {
+// g();
+//}
diff --git a/test/uvw/emitter.cpp b/test/uvw/emitter.cpp
index 602eeae..878455a 100644
--- a/test/uvw/emitter.cpp
+++ b/test/uvw/emitter.cpp
@@ -3,13 +3,6 @@
#include <uvw/emitter.h>
-struct FakeEvent { };
-
-struct TestEmitter: uvw::Emitter<TestEmitter> {
- void emit() { publish(FakeEvent{}); }
-};
-
-
TEST(ErrorEvent, Functionalities) {
auto ecode = static_cast<std::underlying_type_t<uv_errno_t>>(UV_EADDRINUSE);
@@ -24,7 +17,6 @@ TEST(ErrorEvent, Functionalities) {
ASSERT_TRUE(static_cast<bool>(uvw::ErrorEvent{ecode}));
}
-
TEST(Emitter, EmptyAndClear) {
TestEmitter emitter{};
diff --git a/test/uvw/handle.cpp b/test/uvw/handle.cpp
index 8cea4c0..3351d7b 100644
--- a/test/uvw/handle.cpp
+++ b/test/uvw/handle.cpp
@@ -2,17 +2,6 @@
#include <uvw.hpp>
-struct fake_handle_t { void *data; };
-
-
-struct FakeHandle: uvw::Handle<FakeHandle, fake_handle_t> {
- using Handle::Handle;
-
- template<typename... Args>
- bool init(Args&&...) { return initialize([](auto...){ return true; }); }
-};
-
-
TEST(Handle, Functionalities) {
auto loop = uvw::Loop::getDefault();
auto handle = loop->resource<uvw::AsyncHandle>();
@@ -45,7 +34,6 @@ TEST(Handle, Functionalities) {
ASSERT_NO_THROW(handle->fileno());
}
-
TEST(Handle, InitializationFailure) {
auto loop = uvw::Loop::getDefault();
auto resource = loop->resource<FakeHandle>();
diff --git a/test/uvw/thread.cpp b/test/uvw/thread.cpp
index add6c7e..868bb7b 100644
--- a/test/uvw/thread.cpp
+++ b/test/uvw/thread.cpp
@@ -1,6 +1,7 @@
#include <gtest/gtest.h>
#include <uvw.hpp>
+
TEST(Thread, Run) {
auto loop = uvw::Loop::getDefault();
auto has_run = std::make_shared<bool>();
diff --git a/test/uvw/tty.cpp b/test/uvw/tty.cpp
index 1ea5027..c057113 100644
--- a/test/uvw/tty.cpp
+++ b/test/uvw/tty.cpp
@@ -1,7 +1,6 @@
#include <gtest/gtest.h>
#include <uvw.hpp>
-
TEST(TTY, Functionalities) {
auto loop = uvw::Loop::getDefault();
auto handle = loop->resource<uvw::TTYHandle>(uvw::StdOUT, false);
diff --git a/test/uvw/util.cpp b/test/uvw/util.cpp
index 077075d..d8242ca 100644
--- a/test/uvw/util.cpp
+++ b/test/uvw/util.cpp
@@ -3,7 +3,6 @@
#include <gtest/gtest.h>
#include <uvw.hpp>
-
template<typename T>
struct tag { using type = T; };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment