views:

284

answers:

3

I am trying to use this code for the Porter stemming algorithm in a C++ program I've already written. I followed the instructions near the end of the file for using the code as a separate module. I created a file, stem.c, that ends after the definition and has

extern int stem(char * p, int i, int j) ...

It worked fine in Xcode but it does not work for me on Unix with gcc 4.1.1--strange because usually I have no problem moving between the two. I get the error

ld: fatal: symbol `stem(char*, int, int)' is multiply-defined: (file /var/tmp//ccrWWlnb.o type=FUNC; file /var/tmp//cc6rUXka.o type=FUNC); ld: fatal: File processing errors. No output written to cluster

I've looked online and it seems like there are many things I could have wrong, but I'm not sure what combination of a header file, extern "C", etc. would work.

+9  A: 

That error means that the symbol (stem) is defined in more than one module.

You can declare the symbol in as many modules as you want. A declaration of a function looks like this:

int stem(char * p, int i, int j);

You don't need the "extern" keyword, although it doesn't hurt anything. For functions declarations, it's implied.

A definition of a function looks like this:

int stem(char * p, int i, int j) 
{
    /* body of your function */
}

The "multiply-defined" error indicates that you have two modules with a definition for the same function. That usually means that you have two files that define the function, or two files that #include a file that defines the function. Normally, you should not put function definitions in files that you #include. Put the definition in a .c, .cpp, or .cc file and just put a declaration in a .h file that you #include.

For example, you could create a stem.h file with this in it:

int stem(char * p, int i, int j);

Then, #include "stem.h".

Daniel Stutzbach
Of course! I was getting so distracted by the unfamiliar aspects of the C code that I didn't see this. Thank you. I'm getting a new error doing it this way in Xcode, but it works in Unix which is the important thing.
eom
A: 

The fact that Whatever.cpp has #include "stem.c" provides the first definition, and specifying stem.c on the compiler command line provides the second definition.

You should break up stem.c into a header file (With just function prototypes) and a .c file which contains the implemention. Include only the header file in Whatever.cpp

Ken Bloom
A: 

You need to add "C". You need to extern "C" { ... } and only actually define the function once. But you can declare it (the prototype) as often as you like.

DeadMG
The first part of this really isn't true for the case of this question. You only need `extern "C"` if you need a C++ function to be able to be called from C code. In this case, it's the other way around and a C function is being called from C++ code.
Tyler McHenry