背景:
我正在尝试在 C 中开发一个类似于 Zelda (NES) 的简单游戏,作为学习 C 的一种方式。我得出的结论是,将所有游戏数据放在一个文件中并不理想。所以我想做的是将每个“区域”分解成它自己的模块。这个“区域”模块将向主程序描述它的属性,例如瓦片地图,触发某些事件的函数,并调用主程序的游戏 API 来操作演员/声音/等。屏幕上。因此,这些模块必须在运行时加载/卸载。本质上,主程序是一个状态机,它使用从这个“区域”模块提供给它的任何数据。
我试图创建这些共享模块,但似乎主程序中定义的函数对区域模块不可见(至少不在同一范围内)。我确定这是因为我链接不正确。所以我所做的是尝试提出一个可行的概念证明。以下是我失败的概念证明:
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
区域.c
#include "api.h"
extern int init(void)
{
int ret = set_name("area 1");
return ret;
}
游戏.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;
}
构建.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.sh
该程序产生:
$ ./游戏
姓名:(空)
我希望看到:名称:区域 1
我想要做的甚至可能吗?如果没有,我还有另一个想法是将所有 API 调用注册到 area 模块……但对我来说,这并不理想。
机器信息:gcc (Ubuntu 4.3.3-5ubuntu4) 4.3.3。