Thing is, you rarely want to share just a buffer anyway. You probably have additional state, locks, etc. So what I do is embed my ByteBuf directly into another structure, which then owns it completely:
typedef struct {
...
ByteBuf mybuffer;
...
} SomeThing;
So we end up with the same amount of pointers (1), but with some unique advantages.