Background:
I'm trying to develop a simple game similar to Zelda (NES) in C as a way to learn C. I've come to the conclusion that having all of the game data in a single file is not ideal. So what I'd like to do is break up each "area" into it's own module. This "area" module will describe to the main program its properties, such as a tile map, functions to trigger on certain events, and call the main program's game API to manipulate actors/sounds/etc. on the screen. So, these modules must be loaded/unloaded at run-time. Essentially, the main program is a state machine that works off of whatever data is supplied to it from this "area" module.
I've tried to create these shared modules but it doesn't seem like the functions defined in the main program are visible to the area module (at least not in the same scope). I'm sure this is because I'm linking it incorrectly. So what I've done is try to come up with a proof of concept that would work. Below is my, failing, proof of concept:
api.h
#ifndef _API_H
#define _API_H
static char *name = 0;
extern int play_sfx(int, int, int);
extern int move_actor(int, int, int);
extern int set_name(char*);
extern char* get_name(void);
#endif
area.c
#include "api.h"
extern int init(void)
{
int ret = set_name("area 1");
return ret;
}
game.c
#include <stdio.h>
#include <dlfcn.h>
#include "api.h"
int main()
{
void *handle = dlopen("/home/eric/tmp/build_shared5/libarea.so", RTLD_LAZY);
int (*test)(void) = dlsym(handle, "init");
(*test)();
dlclose(handle);
printf("Name: %s\n", get_name());
return 0;
}
extern int play_sfx(int id, int times, int volume)
{
// @todo Execute API call to play sfx
return 1;
}
extern int move_actor(int id, int x, int y)
{
// @todo Execute API call to move actor
return 1;
}
extern int set_name(char *p)
{
name = p;
return 1;
}
extern char* get_name(void)
{
return name;
}
build.sh
#!/bin/bash
gcc -o game.o -c game.c
gcc -fPIC -o area.o -c area.c
#,--no-undefined
gcc -shared -Wl,-soname,libarea.so.1 -o libarea.so game.o area.o
gcc -o game game.o -ldl
Build:
$ ./build.sh
The program produces:
$ ./game
Name: (null)
I expected to see: Name: area 1
Is what I'm trying to do even possible? If not, I have one other idea which is to register all the API calls to the area module... but that, to me, is not ideal.
Machine info: gcc (Ubuntu 4.3.3-5ubuntu4) 4.3.3.