游戏引擎开发:无对应头文件时如何引用SO文件?
没有头文件时引用SO共享对象的方法
嘿,我懂你的处境——你已经把游戏引擎依赖的中间件编译成SO文件了,但现在手头没有对应的头文件,想知道怎么在代码里调用这些库的功能对吧?下面给你两种实用的解决方案,根据你的场景选就行:
方法一:手动声明需要的符号(适合知道API原型的情况)
如果你清楚要调用的库函数、结构体的原型(比如GLFW的glfwInit()、glfwCreateWindow这些公开API),你可以自己手动写一个简易的头文件,把需要用到的符号都声明出来。
举个GLFW的例子,你可以创建一个my_glfw.h:
// 手动声明GLFW的基础类型和函数 typedef void* GLFWwindow; int glfwInit(void); void glfwTerminate(void); GLFWwindow* glfwCreateWindow(int width, int height, const char* title, void* monitor, GLFWwindow* share); void glfwWindowShouldClose(GLFWwindow* window); void glfwSwapBuffers(GLFWwindow* window); // 其他你需要用到的函数/类型声明
然后在你的代码里直接包含这个头文件,CMake里还是保持你原来的导入库链接逻辑就行:
add_library (glfw SHARED IMPORTED) set_target_properties (glfw PROPERTIES IMPORTED_LOCATION ${ENGINE_BINARIES_DIR}/Libraries/Shared/libglfw.so.3.2 ) target_link_libraries(your_engine_executable PRIVATE glfw)
⚠️ 注意:这种方法一定要保证你的声明和SO文件里的实际符号完全匹配(包括返回值、参数类型、调用约定),一旦写错,运行时很容易崩溃或者出现未定义行为。如果能找到对应版本的官方头文件,优先用官方的,别自己瞎写!
方法二:动态加载SO文件(灵活,无需提前链接)
如果你不想手动声明一堆符号,或者不确定要用到哪些函数,可以用POSIX标准的动态链接函数(dlopen、dlsym)在运行时加载SO并获取函数地址。
示例代码如下:
#include <dlfcn.h> #include <stdio.h> int main() { // 加载目标SO文件 void* lib_handle = dlopen("${ENGINE_BINARIES_DIR}/Libraries/Shared/libglfw.so.3.2", RTLD_LAZY); if (!lib_handle) { fprintf(stderr, "Failed to load GLFW: %s\n", dlerror()); return 1; } // 定义函数指针类型,然后获取函数地址 typedef int (*GlfwInitFunc)(void); GlfwInitFunc glfw_init = (GlfwInitFunc)dlsym(lib_handle, "glfwInit"); if (!glfw_init) { fprintf(stderr, "Failed to get glfwInit: %s\n", dlerror()); dlclose(lib_handle); return 1; } // 调用函数 if (glfw_init()) { // 同理,获取其他需要的函数地址 typedef void (*GlfwTerminateFunc)(void); GlfwTerminateFunc glfw_terminate = (GlfwTerminateFunc)dlsym(lib_handle, "glfwTerminate"); if (glfw_terminate) { glfw_terminate(); } } // 用完记得关闭库句柄 dlclose(lib_handle); return 0; }
编译的时候,需要链接dl库,在CMake里加上:
target_link_libraries(your_engine_executable PRIVATE dl)
这种方法的好处是:不需要提前链接库,运行时才加载;也不用写一堆头文件声明。但缺点是每次调用函数都要先获取地址,代码会稍微繁琐一点。
额外提醒
- 如果是C编写的SO库,要注意名字修饰(name mangling)——C会把函数名改成带参数信息的奇怪字符串,这时候你要么知道修饰后的符号名,要么确保库是用
extern "C"导出的符号(像GLFW这种C库就没这个问题)。 - 最稳妥的办法还是尽量找到对应版本的官方头文件,手动声明太容易踩坑了!
内容的提问来源于stack exchange,提问作者StickyFingies
相关产品推荐
相关产品推荐

