Could you give a quick explanation why? I thought the whole point of
the "extern" specifier was to flag that this variable was defined
elsewhere.
Right, but with most platforms' shared library systems, this means
"in another source file that is part of the same shared library",
not "in another shared library" or "in the main executable".
Otherwise, doesn't it imply that the API pointer is
defined in each file that includes arrayobject.h?
i.e. shouldn't headers declare "extern double x" for everything except
the file that actually defines x?
If a dynamically loaded module consists of more than one source file,
then all but one of them (the one which calls import_array()) must
define NO_IMPORT_ARRAY before including arrayobject.h. This is also
the answer to Kevin Rodgers' question.
However, it seems to me that the current arrangement in NumPy has
another serious drawback: it should be impossible to link NumPy
statically with the Python interpreter, due to multiply defined
symbols. And I am rather sure that this was possible many versions
ago, since I used NumPy on a Cray T3E, which does not have shared
libraries.
I checked my own extension modules that export a C API, and they all
declare the API pointer static. This is also what the C API export
section in the "Extending & Embedding" manual recommends. (OK, I admit
that I wrote that section, so that is not a coincidence!)
So perhaps the best solution is to make this static. Client modules
that consist of more than one source code file with PyArray... calls
must then call import_array() once in every such file, or equivalently
pass on the PyArray_API pointer explicitly between the files. That
sounds quite acceptable to me.
In my experience porting other libraries to the Mac I find that most
Unix boxes are not at all upset by what CodeWarrior calls multiple
definitions. The answer in that case was in details that are not
specified in the C standard. Section 4.8 of "A Reference Manual" by
Harbison and Steele goes into the details of how external names are
handled. Most UNIX compilers use the mixed Common Model. In this case
you can define a global any number of times and if there is no
initializer present they are all merged into one much like a Fortran
Common block.
My point is that what I consider lazy coding practice (not using
externs where needed) is tolerated by many C compilers.
I am not competent to comment on the impact of shared libraries on all this.
--
*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-
Rob Managan <mailto://managan@llnl.gov>
LLNL ph: 925-423-0903
P.O. Box 808, L-095 FAX: 925-422-3389
Livermore, CA 94551-0808