[nanomsg] Re: Python bindings for nng

  • From: "Garrett D'Amore" <garrett@xxxxxxxxxx>
  • To: nanomsg@xxxxxxxxxxxxx
  • Date: Mon, 19 Mar 2018 18:43:25 +0000

I think nngpy is a fine name. :-)

I also think getting some operational experience will greatly inform your
decisions about APIs.

I am going to do the same as I look at other runtime bindings.

On Mon, Mar 19, 2018 at 10:31 AM Vincent Nonnenmacher <
vincent.nonnenmacher@xxxxxxxxx> wrote:

thanks.

I will try both Python and Ruby approach to see if there is some ‘common’
way of doing this at their respective level (but I’m much more proficient
in Ruby).

I have also take a look at this ‘first steps’ page (
http://nanomsg.org/gettingstarted/nng/index.html), that is a great
starting point.

I guess, as you mentioned, the first step is having the ‘raw’ lib binding
available to the host langage.

(I will try to make a first commit of ’nngpy’ — if the name is not too
confusing with great Dirkjan Ochtman ’nnpy’ from which it is shamelessly
derived)

Having a high level initialisation for a proper ‘abstraction’ for a
’socket’ adapted for a ‘protocol’ with corresponding options, will come
after.

Then from that ‘instance’ being able to use it in a quite uniform manner
using ‘url’ as a way to pick the proper transport.

If there is the strict minimum langage magic and the code stick to the C
examples as much as possible
I guess abstractions will come naturally as usage and tests come.







On Mon, Mar 19, 2018 at 6:03 PM, Garrett D'Amore <garrett@xxxxxxxxxx>
wrote:

You are correct in that the legacy nanomsg API is probably not the best
point of abstraction.

mangos and nng have very similar abstractions, although unfortunately
they use different names for things.

In nng and in mangos both, the socket is constructed by a
protocol-specific constructor; this makes sense if you think about it.  The
core semantics of the socket — for example PUB vs. SUB vs. REQ, are rather
fundamental, and a socket can only have one of them.

Mangos has the idea of “adding” transports to a socket, whereas NNG is
designed around registering the transports globally (and the standard
transports are all registered by default), and then distinguishing based on
URL.
In retrospect, I could have followed the mangos pattern in NNG, but I
think what I’ve done works well enough.

The C demos are a good starting point, but I think many things in NNG may
not be appropriate for a given language binding.  For example, in some
event driven bindings you may want to wrap around the async API, but not
expose it directly, and ignore the blocking APIs altogether.   Or in a
simpler threaded environment, you may do the reverse.  As another example,
you may want to ignore the supplemental APIs for HTTP, because your runtime
already has excellent support for HTTP clients and servers.

In a *perfect* world, everyone would follow the approach of mangos, and
implement a pure language implementation of these protocols, using
idiomatic methods for the language.  However, as I can well attest, writing
an implementation from scratch isn’t necessarily easy.

So what I would do, is rather than write a very thin language binding,
would be to instead take a look at the APIs, think about the API that would
make the most sense for your environment (think idiomatically — what are
your users going to appreciate?) and then come up with an appropriate
mapping that may include some extra language wrappers to fix up differences.

This is more work than just a thin binding, but the result is far more
satisfying and pleasurable for folks working in your native runtime.

For example, if I were to create a C++ API, I’d wrap some of the integer
socket types and so forth into real C++ objects, with methods on those
objects, and make destruction work via the nng_close() method (or similar)
where appropriate, etc.

You can also expose the underlying raw C APIs in a separate namespace, if
that option is available, for “advanced” use cases.

 - Garrett

On Mon, Mar 19, 2018 at 9:51 AM Vincent Nonnenmacher <
vincent.nonnenmacher@xxxxxxxxx> wrote:


When considering Python bindings for ’nng’,
it appears that porting current ‘nnpy’ Python interface to ’nanomsg’
(e.g  Socket)
is kinda similar to the ‘nng/compat’ approach, where a *Socket* top
class is presented
and rewrapped around ‘transport’ and ‘protocol’ in a ‘reverse’ way.

It seems to me that a proper interface to ‘nanomsg *new generation*’
should break that
and stick more around the new approach of a obtaining a ‘Socket’
from a registered ‘transport’ and then choose a desired ‘protocol’ on
top of this.

If we consider that existing ’nnpy’ could use the ‘nng/compat’ approach
the question is about a new Python (or Ruby as this is my actual target)
high level interface that break once and for all to this new ‘generation’
and let the user choose a lib replacement with minimum fuss and maximum
Compatibility sticking to ’nnpy’ (modifications aren’t difficult from
the point I am now).

for ’nng’ without consideration about ’nanomsg’ compatibility in mind,
does taking the C demos and try to stay as much as possible to this level
is a good approach for this ?

Or this too low-level ?

It seems that both (`async.c` and `reqrep.c` as examples) use a ’server
vs client’
interface approach where a lot of commonality could be deduced from the
‘url’ and from them a `protocol’ is chosen to implement the specific of
a `program`.

I will look toward finding what could be derived from such code
but it would be helpful to have more demos (as the tests as nice
as they are, don’t offer examples at the standard ‘usage level’).

When looking at `mangos` it seems that the ’socket’ is build
on a `protocol` and then `transports` are added to it

```
func node0(url string) {
var sock mangos.Socket
var err error
if sock, err = pair.NewSocket(); err != nil {
die("can't get new pair socket: %s", err)
}
sock.AddTransport(ipc.NewTransport())
sock.AddTransport(tcp.NewTransport())
if err = sock.Listen(url); err != nil {
die("can't listen on pair socket: %s", err.Error())
}
sendRecv(sock, "node0")
}
```

There are  also ’pipes’ and ‘endpoints’ concept that seems very
interesting.

Sorry to ask for your thoughts about this, but some enlightenment
could be useful here ;-)




On Tue, Mar 13, 2018 at 9:15 AM, Vincent Nonnenmacher <
vincent.nonnenmacher@xxxxxxxxx> wrote:

Dirkjan code is based on this to see what to feed to cffi, so this
macro is ‘the’ discriminer.

Thanks for your answers.

note : I haven’t consider including ‘combat’ as the new API sound nicer
and perhaps nnpy could
          be adapted around this one, keeping the same conventions.



On Mon, Mar 12, 2018 at 8:49 PM, Garrett D'Amore <garrett@xxxxxxxxxx>
wrote:

Yes it is.
On Mon, Mar 12, 2018 at 12:17 PM Dirkjan Ochtman <dirkjan@xxxxxxxxxx>
wrote:

On Mon, Mar 12, 2018 at 7:41 PM, Garrett D'Amore <garrett@xxxxxxxxxx>
wrote:

NNG_DECL is used only on Windows really, and is only needed for APIs
that are exposed to applications.  So this includes some header files, 
but
only those that would normally be “installed” where a user application
could link against them.


Is NNG_DECL similar to NN_EXPORT? If so, I think the nnpy usage is
simpler than what you're implying -- nnpy uses it just to simplify the
limited parsing of the header files that it tries to do.

Kind regards,

Dirkjan





Other related posts: