Uvw
Header-only, event based, tiny and easy to use libuv wrapper in modern C++ - now available as also shared/static library!
Install / Use
/learn @skypjack/UvwREADME

Do you have a question that doesn't require you to open an issue? Join the
gitter channel.<br/>
If you use uvw and you want to say thanks or support the project, please
consider becoming a
sponsor.<br/>
You can help me make the difference.
Many thanks to those who supported me
and still support me today.
Introduction
uvw started as a header-only, event based, tiny and easy to use wrapper for
libuv written in modern C++.<br/>
Now it's finally available also as a compilable static library.
The basic idea is to wrap the C-ish interface of libuv behind a graceful C++
API.<br/>
Note that uvw stays true to the API of libuv and it doesn't add anything to
its interface. For the same reasons, users of the library must follow the same
rules which are used with libuv.<br/>
As an example, a handle should be initialized before any other operation and
closed once it is no longer in use.
Code Example
#include <uvw.hpp>
#include <memory>
void listen(uvw::loop &loop) {
std::shared_ptr<uvw::tcp_handle> tcp = loop.resource<uvw::tcp_handle>();
tcp->on<uvw::listen_event>([](const uvw::listen_event &, uvw::tcp_handle &srv) {
std::shared_ptr<uvw::tcp_handle> client = srv.parent().resource<uvw::tcp_handle>();
client->on<uvw::close_event>([ptr = srv.shared_from_this()](const uvw::close_event &, uvw::tcp_handle &) { ptr->close(); });
client->on<uvw::end_event>([](const uvw::end_event &, uvw::tcp_handle &client) { client.close(); });
srv.accept(*client);
client->read();
});
tcp->bind("127.0.0.1", 4242);
tcp->listen();
}
void conn(uvw::loop &loop) {
auto tcp = loop.resource<uvw::tcp_handle>();
tcp->on<uvw::error_event>([](const uvw::error_event &, uvw::tcp_handle &) { /* handle errors */ });
tcp->on<uvw::connect_event>([](const uvw::connect_event &, uvw::tcp_handle &tcp) {
auto dataWrite = std::unique_ptr<char[]>(new char[2]{ 'b', 'c' });
tcp.write(std::move(dataWrite), 2);
tcp.close();
});
tcp->connect(std::string{"127.0.0.1"}, 4242);
}
int main() {
auto loop = uvw::loop::get_default();
listen(*loop);
conn(*loop);
loop->run();
}
Motivation
The main reason for which uvw has been written is the fact that there does not
exist a valid libuv wrapper in C++. That's all.
Build Instructions
Requirements
To be able to use uvw, users must provide the following system-wide tools:
- A full-featured compiler that supports at least C++17.
libuv(which version depends on the tag ofuvwin use)- If you use
meson, libuv will be downloaded for you
- If you use
The requirements below are mandatory to compile the tests and to extract the documentation:
- CMake version 3.13 or later.
- Doxygen version 1.8 or later.
Note that libuv is part of the dependencies of the project and may be cloned
by CMake in some cases (see below for further details).<br/>
Because of that, users don't have to install it to run the tests or when uvw
libraries are compiled through CMake.
Meson
You can use uvw with meson by simply adding it to
your subprojects directory in your project.
To compile uvw from source without using it as a subproject, in the uvw
source directory, run:
$ meson setup build- If you want a static library, add
--default-library=static
- If you want a static library, add
$ cd build$ meson compile
Library
uvw is a dual-mode library. It can be used in its header-only form or as a
compiled static library.<br/>
The following sections describe what to do in both cases to get uvw up and
runningin your own project.
Header-only
To use uvw as a header-only library, all is needed is to include the uvw.hpp
header or one of the other uvw/*.hpp files.<br/>
It's a matter of adding the following line at the top of a file:
#include <uvw.hpp>
Then pass the proper -I argument to the compiler to add the src directory to
the include paths.<br/>
Note that users are required to correctly setup the include directories and
libraries search paths for libuv in this case.
When used through CMake, the uvw::uvw target is exported for convenience.
Static
To use uvw as a compiled library, set the UVW_BUILD_LIBS options in cmake
before including the project.<br/>
This option triggers the generation of a targets named
uvw::uvw-static. The matching version of libuv is also
compiled and exported as uv::uv-static for convenience.
In case you don't use or don't want to use CMake, you can still compile all
.cpp files and include all .h files to get the job done. In this case, users
are required to correctly setup the include directories and libraries search
paths for libuv.
Versioning
Starting with tag v1.12.0 of libuv, uvw follows the
semantic versioning scheme.<br/>
The problem is that any version of uvw also requires to track explicitly the
version of libuv to which it is bound.<br/>
Because of that, the latter wil be appended to the version of uvw. As an
example:
vU.V.W_libuv-vX.Y
In particular, the following applies:
- U.V.W are major, minor and patch versions of
uvw. - X.Y is the version of
libuvto which to refer (where any patch version is valid).
In other terms, tags will look like this from now on:
v1.0.0_libuv-v1.12
Branch master of uvw will be a work in progress branch that follows branch
v1.x of libuv (at least as long as it remains their master branch).<br/>
Documentation
The documentation is based on
doxygen. To build it:
$ cd build$ cmake ..$ make docs
The API reference will be created in HTML format within the directory
build/docs/html.<br/>
To navigate it with your favorite browser:
$ cd build$ your_favorite_browser docs/html/index.html
The same version is also available online for the latest release, that is the last stable tag.
Note
The documentation is mostly inspired by the official libuv API documentation for obvious reasons.
Tests
To compile and run the tests, uvw requires libuv and googletest.<br/>
CMake will download and compile both the libraries before compiling anything
else.
To build the tests:
$ cd build$ cmake .. -DUVW_BUILD_TESTING=ON$ make$ ctest -j4 -R uvw
Omit -R uvw if you also want to test libuv and other dependencies.
Crash Course
Vademecum
There is only one rule when using uvw: always initialize the resources and
terminate them.
Resources belong mainly to two families: handles and requests.<br/> Handles represent long-lived objects capable of performing certain operations while active.<br/> Requests represent (typically) short-lived operations performed either over a handle or standalone.
The following sections will explain in short what it means to initialize and terminate these kinds of resources.<br/> For more details, please refer to the online documentation.
Handles
Initialization is usually performed under the hood and can be even passed over,
as far as handles are created using the loop::resource member function.<br/>
On the other side, handles keep themselves alive until one explicitly closes
them. Because of that, memory usage will grow if users simply forget about a
handle.<br/>
Therefore the rule quickly becomes always close your handles. It's as simple
as calling the close member function on them.
Requests
Usually initializing a request object is not required. Anyway, the recommended
way to create a request is still through the loop::resource member
function.<br/>
Requests will keep themselves alive as long as they are bound to unfinished
underlying activities. This means that users don't have to discard a
request explicitly .<br/>
Therefore the rule quickly becomes feel free to make a request and forget about
it. It's as simple as calling a member function on them.
The Loop and the Resource
The first thing to do to use uvw is to create a loop. In case the default one
is enough, it's easy as doing this:
auto loop = uvw::loop::get_default();
Note that loop objects don't require being closed explicitly, even if they offer
the close member function in case a user wants to do that.<br/>
Loops can be started using the run member function. The two calls below are
equivalent:
loop->run();
loop->run(uvw::loop::run_mode::DEFAULT);
Available modes are: DEFAULT, ONCE, NOWAIT. Please refer to the
documentation of libuv for further details.
In order to create a resource and to bind it to the given loop, just do the following:
auto tcp = loop->resource<uvw::tcp_handle>();
The line above creates and initializes a tcp handle, then a shared pointer to that resource is returned.<br/> Users should check if pointers have been correctly initialized: in case of errors, they won't be.<br/> It also is possible to
Related Skills
node-connect
325.6kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
80.2kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
325.6kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
80.2kCommit, push, and open a PR

