A hook comes in five parts: a declaration (in a header, of course), a hook structure, an implementation (where the hooked functions get called), a call to the implementation, and a hooked function. The first four parts are all provided by the author of the hook, and the last by its user. They are documented in .../include/ap_config.h. Let's cover them in order. First, the declaration. This consists of the return type, the name of the hook, and an argument list. Notionally, it's just a function declaration with commas in strange places. So, for example, if a hook is going to a call a function that looks like:
int some_hook(int,char *,struct x);
then the hook would be declared like this:
AP_DECLARE_HOOK(int,some_hook,(int,char *,struct x))
Note that you really do have to put brackets around the arguments (even if there's only one) and no semicolon at the end (there's only so much we can do with macros!). This declares everything a module using a hook needs, and so it would normally live in an appropriate header.
The next thing you need is the hook structure. This is really just a place that the hook machinery uses to store stuff. You only need one for a module that provides hooks, even if it provides more than one hook. In the hook structure you provide a link for each hook:
APR_HOOK_STRUCT( APR_HOOK_LINK(some_hook) APR_HOOK_LINK(some_other_hook) )
Once you have the declaration and the hook structure, you need an implementation for the hook — this calls all the functions registered ...