8

This is a C specific question. I am trying to keep everything possible inside the translation unit boundaries, exposing only a few functions through the .h file. That is, I am giving static linkage to file-level objects.

Now, a couple of functions need to be called by other modules, but not directly. My module/file/translation unit subscribes to the other modules, passing a pointer to a function. Then, upon a specific event, the pointer is called with some arguments.

So I am wondering how to make it very obvious that those functions are called from some obscure location.

  • Should they be static or extern (and expose them in the .h) ?
  • Should I include some hint in the name of the functions?
  • Or is it enough to put a comment "called by X"?
1
  • 2
    That's an excellent question. My solution (with which I'm not at all too happy, that's why I'm only putting it in a comment) is to make multiple header files, sensibly named, and grouping functions on the scope I want them to have. For the AStar library I've made i have AStar.h, AStar_private.h, AStar_packagePrivate.h, etc... Commented Feb 12, 2014 at 13:48

5 Answers 5

2

From the perspective of the compilation unit (file), the only thing you should concern yourself with is whether or not the function is available to the outside. Making it available means that it was intended to be called, and you should operate under the assumption that those calls will happen. Your concern with the function itself begins at its entry point. How control gets there in the first place matters only to the code that makes it happen.

Since linkage in every implementation of C I know of is symbolic, anything that calls a function must refer to its symbol:

foo();  /* Direct */

some_function_pointer_t funcs[] = { &foo, &bar, &baz };  /* Indirect */

If you mistakenly declare foo() to be static, your program won't link. If you declare it non-static, you have an exposed function that isn't called. Questions about whether or not a function is used can be resolved by dumping the symbol tables of your object files or searching for it in the sources.

1

So I am wandering how to make it very obvious that those functions are called from some obscure location.

Define "obscure".
Methods should be exposed through well-defined "interfaces" and, as Shivan Dragon has already suggested, those "interfaces" are your .h files. If you don't give another program the "right" header file then it can't call the method.

Should they be static or extern (and expose them in the .h) ?

static might be OK so long as you don't have any class[-like constructs] that contain instance data.
extern means you don't actually implement it at all; an implementation is "acquired" from elsewhere during the linking process.

Should I include some hint in the name of the functions?

Or is it enough to put a comment "called by X"?

Absolutely not.

Comments like this, no matter how well-meaning, are obsolete the moment you finish writing them.

2
  • Addressing your first point, the functions are called as follows. My component includes an external .h file. It calls a function from there and gives to it a pointer to one of the module's own functions. Later the external code calls whatever is at that pointer. Thus my function is being called by someone, who does not include my header file, rather I include his.
    – Vorac
    Commented Feb 12, 2014 at 14:45
  • 1
    Concerning the second point, as far as my understanding goes, object, defined at file scope have external linkage by default; therefore the extern keyword is redundant`.
    – Vorac
    Commented Feb 12, 2014 at 14:47
0

If callback functions are defined within your module and the user will never provide one of his own, I think you can use a placeholder during initialization phase. The placeholder is typically an enum which is then internally translated to the right static function.

0

I would still make them static (they are not intended to be linked to and called by just anyone), and mark their purpose as callbacks supplied to external functions in their name.

static because I try to hide what I can hide, as much as I can hide it.

Mark them in their name, because a), comments get out of date, and b), it becomes obvious at the place where the callback is supplied that this function is intended to be used that way: this basically makes it a red flag to be taking the address of a function that doesn't follow the naming convention.

0

Scope modifiers should be used primarily as information for the compiler, not as a form of "close enough" documentation. The use of static in particular permits a C compiler to make the function unusable from outside the module, including as a callback - not what you want, even though it may work with your current compiler.

Of course you should add a comment to the code, since you can see it is a potentially confusing situation. Anything unusual or unexpected needs a suitable comment. But, as stated in other answers, comments can go unread or become out-of-date.

So, the only option left is to name the function to indicate it is a callback. Most examples I have seen use _callback or _cb as a suffix, or cb_ as a prefix. Use the long form if callbacks are unusual in your code, the short form if they are common.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.