The Python documentation claims that the following does not work on “some platforms or compilers”:
int foo(int); // Defined in another translation unit.
struct X { int (*fptr)(int); } x = {&foo};
Specifically, the Python docs say:
We’d like to just assign this to the tp_new slot, but we can’t, for
portability sake, On some platforms or compilers, we can’t statically
initialize a structure member with a function defined in another C
module, so, instead, we’ll assign the tp_new slot in the module
initialization function just before calling PyType_Ready(). —http://docs.python.org/extending/newtypes.html
Is the above standard C89 and/or C99? What compilers specifically cannot handle the above?
According to n1570 6.6 paragraph 9, the address of a function is an address constant, according to 6.7.9 this means that it can be used to initialize global variables. I am almost certain this is also valid C89.
However,
On sane platforms, the value of a function pointer (or any pointer, other than
NULL) is only known at runtime. This means that the initialization of your structure can’t take place until runtime. This doesn’t always apply to executables but it almost always applies to shared objects such as Python extensions. I recommend reading Ulrich Drepper’s essay on the subject (link).I am not aware of which platforms this is broken on, but if the Python developers mention it, it’s almost certainly because one of them got bitten by it. If you’re really curious, try looking at an old Python extension and seeing if there’s an appropriate message in the commit logs.
Edit: It looks like most Python modules just do the normal thing and initialize type structures statically, e.g.,
static type obj = { function_ptr ... };. For example, look at themmapmodule, which is loaded dynamically.