#17382 - darknet - Sun Mar 07, 2004 3:31 am
I have, as usual, scanned the forums + misc docs and found questions similar to the one I am about to ask but none that quite answer my dilemma, so here goes:
My project consists of a number of mini-games and one main driver program. As of right now, theres only one mini-game and there is a major problem with a well-known linker error.
My drawMode3Background function is declared in "video.h" as such, in pseudocode:
Code: |
extern void drawMode3Background(unsigned short*, const unsigned short*);
|
It is DEFINED in video.c as follows:
Code: |
#include "video.h"
void drawMode3Background(unsigned short* d, const unsigned short* s) { .......implementation......; }
|
Now, i use that function in my mini game .cpp file (textAdventure.cpp) AND in my main driver file (main.cpp) for various reasons. The error i'm getting is that in the textAdventure.o file there are "multiple definitions" of the drawMode3Bitmap function.
How can this be resolved? I need that function both in my mini-game and my driver. Right now for it to work i have basically shoved all of the text adventure code directly into the main driver and that works fine obviously, but also displays poor form.
I have properly included #ifndef -> #endif in my video.h file, and i include "video.h" both in the driver and in the text adventure file. Modifying the project to not include it in one place and in another had no effect. I have also messed with not making the function extern (since it is inherently is right?) and making it extern, as displayed above.
Any help is greatly appreciated, thanks alot for your time,
-Mike
#17385 - poslundc - Sun Mar 07, 2004 4:12 am
First of all, you're right that you don't need the extern keyword for function prototypes. It's a good idea to take it out since declaring a function and then declaring an extern prototype to it in the same file could very well cause multiple definitions. Although if you've tried removing it then I suppose that isn't causing the problem, but best to take it out anyway.
Second of all, this is probably just a misspelling, but I notice that you say that there are multiple definitions of drawMode3Bitmap, not Background. Do you have a separate function that goes by this name that might be causing the problem?
Third: I know you say you use #ifndef -> #endif, but have you set it up to properly prevent multiple inclusion? eg.
Code: |
#ifndef _VIDEO_HEADER_
#define _VIDEO_HEADER_
... contents of the header file ...
#endif |
Other than that, everything you've done seems kosher, so if you still can't figure it out try posting more code.
Dan.
#17391 - darknet - Sun Mar 07, 2004 6:47 am
Thanks for the quick output Dan.
I did set up the ifndefs and everything correctly. I mistyped in my message about the drawMode3Bitmap/Background. Here is a little more info that hopefully puts up a red flag:
-I am compiling/linking/building with VisualHAM
-I am mixing c files with c++ files. In particular, the c files are the headers and their respective .c implementations, whereas the main driver is a c++ file. This is done because I use object orientation for a few of my games that I will have.
Here is a tiny bit of my actual code if that will help anybody.
MAIN.CPP:
Code: |
//general hardware includes
#include "sprite.h"
#include "timer.h"
#include "dma.h"
#include "interrupt.h"
#include "buttons.h"
#include "video.h"
.......
.......
int main() {
setMode(MODE_3 | BG2_ENABLE);
drawMode3Background(videoBuffer, firstDay_Bitmap);
.... }
|
that function call is declared and implemented in the header file (since it wont work if i put it in a .c file!!!) as such:
Code: |
void drawMode3Background(unsigned short* destination, const unsigned short* source) {
int i;
for(i = 0; i<38400; i++) {
destination[i] = source[i];
}
}
|
If any other code would be helpful and anyone is willing to give it a few minutes, let me know.
Thanks alot for reading,
-Mike
#17394 - DarkPhantom - Sun Mar 07, 2004 8:41 am
darknet wrote: |
that function call is declared and implemented in the header file (since it wont work if i put it in a .c file!!!) |
If we were programming DOS or Windows with a borland or microsoft compiler I would tell you that your problem is definately that you are putting the implementation in the header file. I'm not nearly as experienced as with GCC and the like as I am with Turbo C++ and Visual C++ but I'm pretty sure this is where the problem is.
I was explaining this same problem the people in class with me the other day. You see, basically when you include a header file, the compiler copy and pastes the contents of the header file into the c or cpp file before it tries to compile anything. As a result, if you put actual code in a header file, that code will appear in the object file of every source file compiled with that header included. So, you really are having multipul definitions of the function -- the linker isn't mistaken. The best way to fix this is to move the code to a its own source file.
I was paying attention. I know you said you were having trouble with getting it to work in its own source file. I can honestly say I can't see how. It should work fine even if you are mixing c with c++ and even with assembly. My suggestion is to move the code back to it's own source file and post the problem that you having with that. I'm sure that we'll beable to help you figure out what problem you are having with it.
On a related note, the #ifndef that Dan mentioned won't help here as long as you are defining code in the header file. Don't get me wrong, #ifndef is an excellent practice that I use all the time. The problem here is that the #define will only live so long as the compiler is running and is lost when it exits. When you build a program, the compiler is invoked once for each source file (assuming that each source file needs to be built). All that the #ifndef ensures is that the information in the header won't be included twice in the same object file (or .s file in the case of GCC). Since that define doesn't carry over between building one.c and two.c it won't stop the compiler from putting the same code in both files. In general, I think that writing any code in header files should be avoided like the plague.
On an unrelated note, I love mini games! Do you have demo of what you've built so far?
_________________
"head straight for your goal by any means
there is a door that you've never opened
there is a window with a view you've never seen
get there no matter how long it takes"
-Theme of Shadow, Sonic Adventure 2
#17406 - Paul Shirley - Sun Mar 07, 2004 2:43 pm
removed
Last edited by Paul Shirley on Sun Mar 28, 2004 9:02 pm; edited 1 time in total
#17413 - poslundc - Sun Mar 07, 2004 4:10 pm
I will echo this sentiment. Never, ever put executable code in a header file. That includes functions AND variable definitions.
Limit yourself to structures/typedefs, #defines and #includes, extern variable references and function prototypes. Inlined functions are probably okay as well, I suppose.
Put your function in a separate .c file, and just put the prototype in the .h file. I don't know anything about VisualHAM so I can't tell you how to fix your compile problem, but I can tell you that this is what's causing your current problem. Go fix it. :)
Dan.
#17429 - darknet - Sun Mar 07, 2004 11:25 pm
That "extern C" tip eventually made everything kosher, thanks a whole bunch.
Funny thing was though, it only worked when I compiled the files in a certain order (by tweaking my makefile) --so far so good though.
Thanks once again, its a relief to see my project properly structured !
-Mike
#17434 - Paul Shirley - Mon Mar 08, 2004 2:39 am
removed
Last edited by Paul Shirley on Sun Mar 28, 2004 9:02 pm; edited 1 time in total
#17475 - darknet - Tue Mar 09, 2004 2:31 am
The IDE i am using, VisualHAM, generates its own makefile, and upon further inspection, everything does work out regardless of the order of things.
The project is defined as a c++ project and uses some C headers / source files, hence the earlier confusion + errors.
Thanks again,
-Mike