Linking to a global variable in a static library fails

J

Jaco Naude

Hi,

I'm using a static library in my application which links fine except
for a few global variables. The static library only contains a bunch
of .cpp and .h files and the global variables are defined as follows:

extern unsigned mgl_numg, mgl_cur;
extern float mgl_fact;
extern long mgl_gen_fnt[516][6];
extern short mgl_buf_fnt[246080];
const float mgl_fgen = 4*14;
extern mglTeXsymb mgl_tex_symb[];

This gives the following linker errors:

1>mathgl.lib(mgl_font.obj) : error LNK2001: unresolved external symbol
"short * mgl_buf_fnt" (?mgl_buf_fnt@@3PAFA)
1>mathgl.lib(mgl_font.obj) : error LNK2001: unresolved external symbol
"float mgl_fact" (?mgl_fact@@3MA)
1>mathgl.lib(mgl_font.obj) : error LNK2001: unresolved external symbol
"struct mglTeXsymb * mgl_tex_symb" (?mgl_tex_symb@@3PAUmglTeXsymb@@A)
1>mathgl.lib(mgl_font.obj) : error LNK2001: unresolved external symbol
"long (* mgl_gen_fnt)[6]" (?mgl_gen_fnt@@3PAY05JA)
1>mathgl.lib(mgl_font.obj) : error LNK2001: unresolved external symbol
"unsigned int mgl_cur" (?mgl_cur@@3IA)
1>mathgl.lib(mgl_font.obj) : error LNK2001: unresolved external symbol
"unsigned int mgl_numg" (?mgl_numg@@3IA)

When I remove the extern keywords the linker errors are gone, except
for the mgl_tex_symb[] variable. Removing the extern keyword are not
an acceptable solution though since these variables are used by
another .cpp file in the library.

Is there something special about linking to global variables in a
static library? Should they be defined in the header which is included
in the main program as well? The library is a third party library so I
do not really want to start changing things in it, hopefully this can
be avoided by doing something in the header.

My environment is Visual Studio 2008 and both the application and
library is compiled with it.

Thanks
Jaco
 
J

James Kanze

I'm using a static library in my application which links fine
except for a few global variables. The static library only
contains a bunch of .cpp and .h files and the global variables
are defined as follows:
extern unsigned mgl_numg, mgl_cur;
extern float mgl_fact;
extern long mgl_gen_fnt[516][6];
extern short mgl_buf_fnt[246080];
const float mgl_fgen = 4*14;
extern mglTeXsymb mgl_tex_symb[];

With the exception of mgl_fgen, those aren't definitions; just
declarations. Where are the variables defined?

[...]
When I remove the extern keywords the linker errors are gone,
except for the mgl_tex_symb[] variable.

Without the 'extern', or with an initializer, these become
definitions. Except for mgl_tex_symb, which becomes an error
(and shouldn't compile).
Removing the extern keyword are not an acceptable solution
though since these variables are used by another .cpp file in
the library.

In other words, the extern declarations should be in a header
file. But you still need a definition somewhere. For "objects"
(i.e. data, but not references, functions or types), a
declaration at namespace scope is a definition if either 1) it
doesn't contain the storage class specifier "extern", or 2) it
has an explicit initializer. (And I know, there's nothing
really logical about this. It's just the way it is.)
Is there something special about linking to global variables
in a static library?
No.

Should they be defined in the header which is included in the
main program as well?

Not defined, but if the main program uses them, they should be
declared. As I said, the "standard" solution is to declare them
in a header, and include that. If the declarations differ in
the slighest detail, all sorts of problems may occur, and the
simplest way of ensuring that they don't differ is to only have
one instance of them, in a header.
The library is a third party library so I do not really want
to start changing things in it, hopefully this can be avoided
by doing something in the header.

Are you sure you've compiled and included all of the source
files in the library. If there's only a declaration, and no
definition, this shouldn't compile and link anywhere (but it is
formally undefined behavior, so it's just possible that some
compiler accept it).

If I understand the C standard correctly, it's rules ultimately
lead to the same results (although they are stated in a
radically different manner).
My environment is Visual Studio 2008 and both the application
and library is compiled with it.

It shouldn't make a difference, although as I daid, it's
undefined behavior, so the standard doesn't really require an
error.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,226
Members
46,815
Latest member
treekmostly22

Latest Threads

Top