-
Notifications
You must be signed in to change notification settings - Fork 138
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP: Add C++ bindings #332
base: main
Are you sure you want to change the base?
Conversation
@paroga Thank you for the contribution. I have to say that I am not a C++ developer so it will be difficult for me to review and judge of the interest of this. What I can say is that I feel that most users of the NATS C client are actually C++ developers, and I am not sure what difficulty they have encountered (or not) in using this library. There is another user: @HannaKraft that has opened a PR in the past for a C++ wrapper (#261), not sure if that would have been equivalent. In conclusion, myself not being at all familiar with C++, I would like to have other opinions on the value of this proposed change. Thanks! |
the three main selling points of my wrapper are:
I personally do not see big difficulties. it has a nice and clean API. this wrapper just makes it possible to take advantage of the C++ features (RAII, better type system)
I saw that PR too, but I did not find any related code |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Simple comments for now, would love some feedback from others.
@@ -0,0 +1,65 @@ | |||
// Copyright 2015-2020 The NATS Authors |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copyright should be: "Copyright 2020 The NATS Authors" since this is a new file.
nats::Connection connection(options); | ||
nats::Subscription sub = connection.Subscribe<Handler, &Handler::msg>("subject", &hh); | ||
|
||
nats::Statistics stat; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if you meant to use this but did not?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's just an example that it does not leak memory, but i agree that the example could be improved. for now i only wanted to include a simple one to show the basic idea
void msg(nats::Connection & nc, nats::Subscription & sub, nats::Msg && msg) | ||
{ | ||
std::string data(msg.GetData(), msg.GetDataLength()); | ||
std::cout << id_ << " received: " << msg.GetSubject() << " - " << data << std::endl; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mentioned that you don't need to call natsMsg_Destroy() here. Is your binding auto-generating calls to this when the callback returns?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, exactly. since the ownership is passed into the callback msg
will be destroyed when the function gets out of scope (and msg
has not been moved or released) in the destructor
The example usage code looks good. We made some small wrappers for what we used and that's been good enough. My issue is more that nats.c itself is more of a framework than a library causing it to be hard to integrate in our application. Also all the heartbeat and timeout edge case bugs we need to work around. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I uploaded the generated output for reference: https://gist.github.com/paroga/f9fd44a32e8860cc94d05fd2beed71f4
void msg(nats::Connection & nc, nats::Subscription & sub, nats::Msg && msg) | ||
{ | ||
std::string data(msg.GetData(), msg.GetDataLength()); | ||
std::cout << id_ << " received: " << msg.GetSubject() << " - " << data << std::endl; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, exactly. since the ownership is passed into the callback msg
will be destroyed when the function gets out of scope (and msg
has not been moved or released) in the destructor
nats::Connection connection(options); | ||
nats::Subscription sub = connection.Subscribe<Handler, &Handler::msg>("subject", &hh); | ||
|
||
nats::Statistics stat; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's just an example that it does not leak memory, but i agree that the example could be improved. for now i only wanted to include a simple one to show the basic idea
@paroga You said that you wanted to do more cleanup first, so not merging as-is. Also, I tried to test this on macOS and did
Also help me understand: is that something users will run in their local install or will we have to commit nats.hpp to this repo? If so, will have to look at dependencies for license purposes. |
on Linux
ideally |
Humm... so I tried on my Linux VM (ubuntu) and first I had to make this change to my cmake file:
apparently this is because of my CMake version. Then, after installing python, pip3 and then pip3 install as you suggest, I am now getting:
This worries me a little bit if I have to generate the nats.hpp file for each release and I am having these kind of issues. If it was entirely up to the user of the library to generate that, that would be ok, but if I am responsible to maintain it (and update for each release), I would like it to be friction free. |
sorry for the troubles. could you tell me which Linux version do you want to use exactly? i just made it work with my system until now (since i wanted to get some general feedback frist), but would like to make it as friction free as possible if it gets accepted. what do you think about an docker container for generating |
@paroga I run on a iMac with docker terminal a Ubuntu image:
Having a docker container that would be used to generate the header could work. I don't mind generating manually before each release (if it needs to be committed in this repo), but I would want to have no trouble generating it, that's all :-) |
I applied the changes from @paroga to a current version of the code and created a The code can be found here: To generate the bindings do: docker build -t nats.c .
docker run -v $(pwd)/src:/src -v $(pwd)/scripts:/scripts -v $(pwd)/src:/dest nats.c I used two of the existing examples from the getting_started directory and rewrote them with the c++ header. Biggest Problem right now is, that it wont build. Something somehow gets confused and it tries to use The API for |
This will add a thin wrapper around the C functions to make the development in C++ less painfull.
A python script will generate
nats.hpp
directly fromnats.h
with the Clang Python bindings and therefor no additional work is required for maintaining them.cpp_generator.py
needs some cleanup before merging, but I want some feedback about the general idea first.To test it the installation of
clang
andmako
(pip3 install clang mako
) is required.