Linking error when compiling C and C++ code with g++
I am integrating a medium-sized (10,000 or so lines) program written in C into a C++ program. I have created a new class, BWAGenome
as an interface to the C code, so any access to the C functions is encapsulated. I am compiling everything with the g++
compiler. The .o files are all generated correctly, but when I attempt to link them together into a final executable, the compiler complains that it cannot find the symbols. Here is the error message I get:
Undefined symbols:
BWAGenome::BWTRestoreBWT(char const*)", referenced from:
BWAGenome::BWAGenome(char const*)in BWAGenome.o
"BWAGenome::GetMatches(unsigned int, int, bwt_t*, bwt_t*, bwt_t*, bntseq_t*, bntseq_t*)", referenced from:
BWAGenome::getMatches(unsigned int, int)in BWAGenome.o
These functions are all in the C++ class I made. They wrap functions in the C code, but I don't understand at all how the symbols could be undefined.
A few details about the code and what I have done so far:
- Everything is compiled with
g++
, so if I understand correctly I don't need theextern "C" {};
surrounding the c header files I include. - All of the code compiles correctly individually. The error only occurs during linking.
- I heard somewhere that the C code might need to be called from static functions, so I have tried wrapping each call to a C function inside a static class method and calling that instead.
Any ideas on how to solve this problem?
edit: added definitions开发者_Python百科 and declarations of BWTRestoreBWT and GetMatches
//definition in BWAGenome.h
static bwt_t * BWTRestoreBWT(const char *fn);
//declaration in BWAGenome.cpp
static bwt_t * BWTRestoreBWT(const char *fn) {
return bwt_restore_bwt(fn);
//bwt_restore_bwt is a function in the C code that I am attempting to integrate
}
second edit: After much soul searching I realized the problem was pretty unrelated to most of what I thought it was. See my answer for details.
I notice that it's looking for BWAGenome::BWTRestoreBWT
and BWAGenome::GetMatches
. Those are member functions its looking for, not root namespace global free functions.
Try changing calls to BWTRestoreBWT
that are meant to be calls to your C function to be calls to ::BWTRestoreBWT
in your code and see what happens. Do the same for calls to GetMatches
.
And the person who told you that C functions need to be called from static C++ functions is dead wrong. That would force you to wrap the standard library in C++ static functions, and that's just silly.
try using nm program to get an output of symbols defined and referenced in your programs:
nm file.o | grep BWTRestoreBWT
You should see your symbols with either T or U. T means the name is defined, the later means the symbol is not defined but called. in order to link, for each U there must be corresponding T.
Make sure your functions do not have inline qualifiers unless they defined in header files.
The more I think about this problem, the more it looks like you have the functions declared in your class declaration, but you have no corresponding definition for the functions.
For example, this example compiles just fine but produces the same linker errors you're seeing:
typedef unsigned int bwt_t;
typedef unsigned int bntseq_t;
class BWAGenome {
public:
BWAGenome( char const* name);
void BWTRestoreBWT( char const* name);
void GetMatches( unsigned int, int, int, bwt_t*, bwt_t*, bwt_t*, bntseq_t*, bntseq_t*);
void getMatches( unsigned int, int);
};
BWAGenome::BWAGenome( char const* name)
{
BWTRestoreBWT( name);
}
void BWAGenome::getMatches( unsigned int x, int y)
{
GetMatches( x, y, 0,0,0,0,0,0);
}
int main()
{
return 0;
}
Are the functions BWTRestoreBWT()
and GetMatches()
supposed to be part of class BWAGenome
or are they the C functions that are being wrapped? If the latter, then that's an indication that you're including the header for those functions in the wrong place (and that they do, in fact, probably need to have an extern "C"
linkage specification added).
Edit in response to new information in the question:
In your edited question you say:
//definition in BWAGenome.h
static bwt_t * BWTRestoreBWT(const char *fn);
//declaration in BWAGenome.cpp
static bwt_t * BWTRestoreBWT(const char *fn) {
return bwt_restore_bwt(fn);
//bwt_restore_bwt is a function in the C code that I am attempting to integrate
}
Because of the errors that are in your original question, I can only assume that the declaration of BWTRestoreBWT()
in BWAGenome.h
is inside of class BWAGenome
, like so:
class BWAGenome {
// etc...
static bwt_t * BWTRestoreBWT(const char *fn);
// etc...
};
This means that BWTRestoreBWT()
is a member of class BWAGenome()
so its definition should look like (note the BWAGenome::
scoping operator):
//declaration in BWAGenome.cpp
static bwt_t * BWAGenome::BWTRestoreBWT(const char *fn) {
return bwt_restore_bwt(fn);
//bwt_restore_bwt is a function in the C code that I am attempting to integrate
}
Or you can move the declaration of BWTRestoreBWT()
outside of class BWAGenome
(more formally known as 'namespace scope').
That should fix your current linker error. If you now get an error about something with a name similar to bwt_restore_bwt
not being found, then you'll know you need to do extern "C"
for the C functions as well.
Have you told the linker where to find a library/object that contains the BWAGenome::BWTRestoreBWT
function? Since you compile everything separately, you must link the output .o files explicitly.
The two reasons that may cause this link error are
- there is a definition of the saught names, but you didn't give it to the linker
- the object file you give the linker does not contain the method - i.e. you didn't implement it (or thought you did, but gave the implementation a 'wrong' name)
if you use static keyword with non-class member function, that function will have local linkage, meaning it is not going to be visible outside your compilation unit, i.e. .cpp file. you either have to get it of static keyword, or put function body into your include file.
In context of class member function, static has different meaning. In this case, static allows function to be called without instantiating class object.
Have you checked that you really have the identically-shaped function declared?
It's looking for BWAGenome::BWTRestoreBWT(char const*)
, but maybe you have BWAGenome::BWTRestoreBWT(char *)
(without a const
) declared instead?
The error was in the order I was linking the object files together. I needed to link in the C code first, and then the BWAGenome class I created to call it. The linker couldn't find the C code symbols because they weren't linked yet. Thanks for all your help though. I imagine I frustrated some people, but thanks anyways.
精彩评论