[nanomsg] Re: RFC: Error code query API

  • From: Martin Sustrik <sustrik@xxxxxxxxxx>
  • To: nanomsg@xxxxxxxxxxxxx
  • Date: Thu, 14 Mar 2013 01:47:06 +0100

Hi Evan,

Let me write down some random thoughts on the topic...

Header files provide users with an ability to reference numeric constants by names rather than hard-coding the values. For example:

#define NN_DONTWAIT 1

Some users (different FFI bindings) are not able to access the header files though and rather rely on accessing nanomsg ABI directly. Not to disadvantage these users we should closely mimic the reference-by-name ability provided by header files and expose it via ABI. For example:

nn_symbol ("NN_DONTWAIT") => 1

Comment: Different symbols have different semantics. Some are basically part of the ABI and never change (e.g. NN_DONTWAIT or EFSM). Values of some symbols vary depending on the operating system (e.g. EAGAIN). Yet other symbols change with different versions of the library (e.g. NN_VERSION_MINOR). The important point here is that we should not require users (binding authors) to understand these subtle differences in semantics, for example by forcing them to hard-code values of certain symbols while asking them to dynamically resolve values of other symbols. The user should simply rely on the ability to convert symbolic names into numeric values and ignore the differences in semantics.

Btw, it looks like if we decide to proceed in this direction, it will make nn_version() function obsolete -- version numbers can be resolved by nn_symbol() function the same way as any other symbol would be.

Finally, many language bindings are able to create symbols in run-time. It would make sense if these bindings could automatically enumerate all the symbols exposed by nanomsg and insert them into the user's environment. Pseudocode (hypothetical binding for language foo):

const char *name;
int value;
int i = 0;
while (1) {
    nn_get_symbol (i, &value, &name);
    if (errno == EINVAL)
        break;
    foo_create_symbol (name, value);
    ++i;
}

Thoughts?
Martin

On 13/03/13 22:24, Evan Wies wrote:
Hello all,

This message is particularly to nanomsg language binding implementers,
but might be interesting to other people.

I was writing a Lua language binding using the LuaJIT FFI. This does not
have a C-compiled component, so the C pre-processor is not available to
the binding. So I ran into the problem where the platform-specific error
codes could not be easily determined.

To assist, I wrote the function `nn_errorcode` so one could query them
dynamically:

https://github.com/neomantra/nanomsg/commit/ae6047d9fb797b23e0e1088e5b557b37635e0e88

/* Given a symbolic error name (e.g. "ETERM"), returns its associated
code. */
/* Returns -1 if the error name is not used by nanomsg. */
NN_EXPORT int nn_errorcode (const char *errname);

So for example, you could write `nn_errorcode("EINVAL")` and get back
`22`. In my case, when by binding is loaded, I'd scan through all the
error codes and assign the values appropriately.

Some questions:

* Is this function useful for other language bindings? Is there anything
else you need for it to benefit you?

* While discussing this issue on IRC with Martin, he was pondering if
all the constants should be available dynamically. Would that be of
interest, or are the per-platform error codes enough?

Also please reply with other issues/comments you may have.

Regards,
Evan



Other related posts: