Reputation: 20184
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:
g++
, so if I understand correctly I don't need the extern "C" {};
surrounding the c header files I include.Any ideas on how to solve this problem?
//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.
Upvotes: 0
Views: 1348
Reputation: 20184
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.
Upvotes: 0
Reputation: 51555
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.
Upvotes: 1
Reputation: 340426
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.
Upvotes: 2
Reputation: 41519
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
Upvotes: 1
Reputation: 51555
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.
Upvotes: 2
Reputation: 56078
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.
Upvotes: 2
Reputation: 57784
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?
Upvotes: 0