[zeromq-dev] C++ interface

Martin Sustrik sustrik at 250bpm.com
Wed Jan 20 09:05:40 CET 2010

Hi Asko,

>>> I worked on this today - mostly learning the details of the man pages.
>>> I'm not asking for this to be included, but maybe you want to have a 
>>> look. The C++ interface as now can be improved essentially, imho.
>> Changing the API is the most sensitive topic around. It affects 
>> basically everyone so we have to be careful here before moving any 
>> changes upstream.
> Sure. That's why I brought it up rather hastily, since 2.0 is still in 
> beta. I don't really mind either way, since it's so easy to have our own 
> C++ binding (just a modded version of the one file).


>> *   - better error messages
>> The improvement we can introduce straight ahead IMO is adding throw 
>> specifications to individual functions. It improves the code and at 
>> the same time there are no backward compatibility issues.
> Throw mentions in C++ prototypes are actually rather useless. They don't 
> really guarantee anything - net has discussions on this. So I'd prefer 
> "no" on this.
> Google found i.e. this: 
> http://stackoverflow.com/questions/1037575/why-arent-exceptions-in-c-checked-by-the-compiler 

AFAIU exception specification would amount to an assert ensuring that no 
"strange" exception will be thrown by C++ wrapper. You are right. 
There's no much use from that (aside of self-documenting purposes). 
Let's leave it as is.

>> *   - enums instead of flag ints
>> The problem here are name collisions. Stripping off the ZMQ prefix 
>> leaves us with constants such as "rate", "swap" or "sub" which are 
>> likely to collide with identifiers defined elsewhere (with "using 
>> namespace zmq"). It's also worth looking at other language bindings. 
>> Ideal solution would preserve the syntax accross the languages while 
>> still keeping namespacing stuff clear.
> Ah, didn't think of "using" here. True. Then again I don't ever use 
> "using" except for for "std".
> The reason for enums would be that compiler IDEs in my understanding 
> help one select the right values for such calls. At least Visual C# does 
> that on the C# side. I find using ints for this kind of issues disturbing.
> One solution can be to change the C side ints into enums instead, with 
> the current names.

I haven't thought of auto-complete. Using enums instead of defines would 
work. The tradeoff is changing the ABI though.

>> *   - set methods instead of use of enums or ints
>> Set methods would mean adding new code to each language binding each 
>> time new socket option is introduced. That's extremely hard to manage 
>> as there's no single person to understand _all_ the language bindings. 
>> Thus  adding new socket option would turn into major managerial task.
> Yes, but it would make the use of the features convenient. Just think 
> about it.

Rethought it and answer is still no. Socket options are primary 
extensibility mechanism. Introducing this kind of feature would mean 
that language binding maintainers would be able to block individual 
releases for unilimited periods of time. With 10+ language bindings (not 
really there yet, but be there shortly IMO) it would hurt the release 
process badly, even fatally.

>> *   - use of 'zmq::pollitem' instead of C 'zmq_pollitem_t' (more 
>> covering up C details)
>> There's following line in the current trunk:
>> namespace zmq {
>>    typedef zmq_pollitem_t pollitem_t;
>> }
> True, but that forces one to fill in the structures by hand. Use of C++ 
> struct and constructors i.e. covers up the dual zmq-or-posix sockets 
> thingy.

Ah. Ok. Got it. I've missed it's an actual class, not just a typedef.

The zmq_poll thing is kind of unfinished. It was added to the API 
recently and it's not even supported in Java, Python and Ruby binding. 
So what should be done IMHO is to propose a conceptual design for 
polling API that would work for at least C++, Java, Lisp, Python and Ruby.

> This all seems very understandable, for the interfaces coming from the 
> "bottom up". C implementation rules, and decides things.  What would now 
> help is actually making code using the bindings and trying to make it as 
> simple and convenient (in the particular language) as can be. That is, 
> coming back "top down". I think the zmq usage needs that.


> If it's a managerial problem then maybe each binding should have a 
> person named to be responsible for it.
> What is important though, is to 
> agree on the logical presentation together, so that documentation needs 
> only be done one. Ruby, Python, C++ should all be conceptually same.

Exactly. See the note above.

> Don't get me wrong. I like zmq and am going to be using it much. That's 
> exactly why I want to throw in my opinions and observations, to help 
> make the product great.

Sure and thanks for that!

>> *   - error handling for 'zmq::poll()' (was missing!!)
>> Ack.

Ok. Let me fix that.

>> *   - added 'const' to methods not changing the object
>> That can make sense at particular points (let's discuss them one by 
>> one), but in overall the semantics of const/non-const-ness in 0MQ is 
>> more complex than what C++ "const" technique is able to describe. For 
>> example, when copying a message (zmq_msg_copy) the content of the 
>> message is shared by 2 zmq::message_t instances. Thus, modification to 
>> non-const object may cause const object to be modified. Etc.
> I noticed that. There are ways to make this splendidly nice, however.

Feel free to propose semantics for constness in 0MQ. If it makes sense 
we can get it in. The problems you would have to address are:

1. context and socket are non-assignable, making any attempt to define 
constness/non-constness on its functions somehow artificial and arbitrary.

2. Because of shared content issue, constness semantics of message 
object is pretty complex and difficult to tame.

> I can help by crafting "as fine as can be" C++ binding, in my opinion. 
> There's absolutely no need for you to take it in, until completely 
> pleased with the results. But I wanted you to be aware of these issues. 
> I don't think I'll be the only one pointing them out.

In overall, I believe we have different goals here. My goal is to keep 
the binding as simple as possible (as you would expect from someone who 
has to maintain large codebase) while your goal is to make the user 
interface as pleasant to use as possible, even to the extent of building 
a non-trivial "usability framework" on top of underlying C API.

Maybe the right solution would be to create a separate "C++ binding on 
steroids" project maintained by yourself that we can link to from 0MQ 
web page. That way you can experiment with the binding without having to 
care about backward compatibility, managerial issues etc. In the ideal 
case C++ users would gradually shift from raw C++ binding to your 
project and once it has reasonable user & developer base, we can merge 
it back to 0MQ proper.


More information about the zeromq-dev mailing list