thanks, seems like great work.
Thinking aloud:
instead of using user space input and output variables, couldn't you just hide those in your library and pass parameter to the compute function, which would just return the result ?
User could still decide if s/he needs the input and output variables, but they would not be shared with your library through pointers.
myController.begin(&setpoint, p, i, d);
...
double input = analogRead(A0);
double output = myController.compute(input);
analogWrite(3, output);
and could have a more condensed code if they are not needed
myController.begin(&setpoint, p, i, d);
...
analogWrite(3, myController.compute(analogRead(A0)));