organise code in multiple files wlalink

Discussion of hardware and software development for Super NES and Super Famicom. See the SNESdev wiki for more information.

Moderator: Moderators

Forum rules
  • For making cartridges of your Super NES games, see Reproduction.
Post Reply
hoit
Posts: 28
Joined: Sun Dec 24, 2017 10:16 am

organise code in multiple files wlalink

Post by hoit »

Hello,

I try to develop on SNES with PVSNESLIB and as long as i use a single code file, everything compile correctly.
I would like to organise my code in multiple file but i didn't find a way to compile it.

For example, i have 3 files :

SimpleSprite.h

Code: Select all

#ifndef SIMPLESPRITE_H
#define SIMPLESPRITE_H
	unsigned char test;
	void SimpleSpriteInit();
#endif
Simpleprite.c :

Code: Select all

#include "SimpleSprite.h"

void SimpleSpriteInit()
{
	test = 'a';
}
main.c :

Code: Select all

#include "SimpleSprite.h"

#include <snes.h>

extern char gfxpsrite, gfxpsrite_end;
extern char palsprite, palsprite_end;


int main(void) {
	SimpleSpriteInit(); // ERROR HERE
	consoleInit();
	oamInitGfxSet(&gfxpsrite, (&gfxpsrite_end-&gfxpsrite), &palsprite, (&palsprite_end-&palsprite), 0, 0x0000, OBJ_SIZE32);

	oamSet(0,  100, 100, 3, 0, 0, 0, 0);
	oamSetEx(0, OBJ_SMALL, OBJ_SHOW);
	
	setMode(BG_MODE1,0); bgSetDisable(0); bgSetDisable(1); bgSetDisable(2);
	setScreenOn();
	
	while(1) {
		WaitForVBlank();
	}
	return 0;
}
This code produce an error when SimpleSpriteInit() is called :

SimpleSprite.obj:SimpleSprite.asm:40: FIX_LABELS: Label "test" was defined more than once.
mn test islsl 0 islfl 0


Here is the file of wla that produce it :
https://github.com/optixx/snes-sdk/blob ... nk/write.c

Do you have informations about that and how can i solve it ?

Thanks in advance for you help.
User avatar
Banshaku
Posts: 2417
Joined: Tue Jun 24, 2008 8:38 pm
Location: Japan
Contact:

Re: organise code in multiple files wlalink

Post by Banshaku »

This is not a wlalink problem but a C problem: you have defined a variable in a header a file and everytime you will include it in another C file, it will try to define a new "test" variable, thus the error "was defined more than once'.

What you should do is define the variable in one C file then if you need to share it, just "extern" it in the file you need to use it. This is what I do in my C project for the nes.
niconii
Posts: 219
Joined: Sun Mar 27, 2016 7:56 pm

Re: organise code in multiple files wlalink

Post by niconii »

Banshaku wrote:This is not a wlalink problem but a C problem: you have defined a variable in a header a file and everytime you will include it in another C file, it will try to define a new "test" variable, thus the error "was defined more than once'.

What you should do is define the variable in one C file then if you need to share it, just "extern" it in the file you need to use it. This is what I do in my C project for the nes.
Shouldn't their #ifndef strategy prevent this, though?

Code: Select all

#ifndef SIMPLESPRITE_H
#define SIMPLESPRITE_H
   unsigned char test;
   void SimpleSpriteInit();
#endif
The first time this header file is included, it checks if SIMPLESPRITE_H is defined. It's not, so it defines it and then declares test and SimpleSpriteInit().

The second time it's included, it checks if SIMPLESPRITE_H is defined. This time, it is, so everything between #ifndef and #endif is skipped.
User avatar
Banshaku
Posts: 2417
Joined: Tue Jun 24, 2008 8:38 pm
Location: Japan
Contact:

Re: organise code in multiple files wlalink

Post by Banshaku »

That's a good question, this is what include guards should do and didn't think much that far when answering since it was my reflex that include = multiple declaration ^^;;;

I think you are right and it shouldn't have cause the issue but I don't know if it good practice to define variables in header but I guess if it makes it easier and you don't have to use extern then it could be one way.
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: organise code in multiple files wlalink

Post by tepples »

I was under the impression that multiple extern declarations of the same thing were allowed, even within one translation unit,* so long as they're identical.


* A translation unit is what you get after the preprocessor has finished handling things like #include and #define.
User avatar
koitsu
Posts: 4201
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: organise code in multiple files wlalink

Post by koitsu »

The placement of variables is being done, IMO, incorrectly in that code. I see this attempted quite often in C code, resulting in an absolute mess of include nonsense that makes no sense. I don't think this concept/issue/matter is taught well (either socially or in CS courses), which is why it's prevalent.

You are quite welcome to declare your functions in an .h file (ex. void SimpleSpriteInit();); this can be used as a form of prototyping and is encouraged. Just be careful.

Your variables, however, need to be declared in the .c file where they're used.

If you have use of global variables, such as unsigned char test;, then this variable declaration should be within what you call main.c.

Then, within what you call SimpleSprite.h, you can have extern unsigned char test;. Any other .c file that has #include "SimpleSprite.h" will then be able to access the global variable called test.

You can also safely #include "SimpleSprite.h" in your main.c without worrying about "double declarations" for test or anything of this sort.

If you want to see an example of how to do this, look at my bsdhwmon code. Specifically, look at f_verbose -- see main.c for its declaration, global.h for its extern and the related VERBOSE() macro that uses it, and all other *.c files that use VERBOSE() (the latter is why it needs to be extern). I could have simply written extern int f_verbose; in every .c file that needed it, but I chose to use a kind of "global macro" that any .c program could use, which references that variable, hence the extern. The linker takes care of the rest.

The short version: do not declare global variables in .h files. Declare the variable within your "main" file, then use extern in other places (either .c files, or an .h file that .c files include).

You can declare typedefs, structs, etc. in .h files of this sort with general safety, though you may need to use an #ifndef/#define approach depending on what it is you're defining.
User avatar
Banshaku
Posts: 2417
Joined: Tue Jun 24, 2008 8:38 pm
Location: Japan
Contact:

Re: organise code in multiple files wlalink

Post by Banshaku »

So I was right to some degree (my gut feeling told me that variables shouldn't be there but I didn't make C in years so I tend to forget things). As for declaring global in main, I wasn't aware of that but when you think about it, it make sense because it's the entry point of the program and any global should be easy to find, thus putting them in that file.

I think I may have done that indirectly without thinking but one of the other "almost" global (i.e. I decided later that it could be used in other modules) was not there. I will refactor my own code a little bit then.

Maybe for the H file, another way to see it is that it define the prototype of what is accessible in the unit (except for inline functions) so definition, like variables, shoudn't be there (does it make sense? ^^;;).
hoit
Posts: 28
Joined: Sun Dec 24, 2017 10:16 am

Re: organise code in multiple files wlalink

Post by hoit »

Thank you for your explanations, it solve my problems !

Have a nice day !
Post Reply