You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于C语言函数指针语法及动态链接库编译的技术咨询

问题1:理解void(*func)(void)和类型转换

先拆解void(*func)(void)——这是C语言里函数指针的声明方式,咱们拆成几部分看:

  • *func被括号括起来,说明func本质是一个指针
  • 后面的(void)表示这个指针指向的函数没有参数
  • 最前面的void表示这个函数的返回值是void类型(也就是不返回任何值)

接下来看dlsym的返回值:dlsym函数的返回类型是void*,这是C语言里的通用指针,可以指向任何数据类型,但它不能直接当成函数指针用。因为函数指针和普通数据指针在底层的表示可能存在差异(虽然很多平台上是一致的,但标准C不允许直接赋值),所以我们需要把dlsym返回的void*转换成我们需要的函数指针类型——也就是void(*)(void)。

你代码里的void (*func)(void) = dlsym(handle, "function");其实是隐式完成了这个转换,不过更标准、更安全的写法应该是显式转换:

void (*func)(void) = (void (*)(void))dlsym(handle, "function");

这样编译器就明确知道:我们把这个通用指针转换成指向“无参、无返回值函数”的指针,后续调用(*func)()的时候就能正确生成函数调用的指令了。

问题2:生成共享库文件list0513.so

你之前只做过普通.c文件的编译,生成共享库只需要给gcc加两个关键参数就行,步骤很简单:

  1. 打开终端,进入list0513dl.c所在的目录
  2. 执行以下编译命令:
gcc -fPIC -shared list0513dl.c -o list0513.so

咱们解释下这两个核心参数:

  • -fPIC:生成位置无关代码(Position-Independent Code),共享库需要能被加载到内存的任意地址,所以必须用这个参数编译
  • -shared:告诉gcc我们要生成的是共享库(.so文件),而不是普通的可执行文件

另外补充一点:编译你的主程序list0513.c的时候,需要链接dl库(因为用到了dlopen、dlsym这些动态链接相关的函数),命令是:

gcc list0513.c -o list0513 -ldl

运行的时候,如果系统找不到list0513.so,可以把当前目录加入动态库搜索路径:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
./list0513

或者编译主程序的时候直接指定运行时的库路径:

gcc list0513.c -o list0513 -ldl -Wl,-rpath=.

这样运行./list0513的时候就不用手动设置环境变量了。

内容的提问来源于stack exchange,提问作者이준영

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:16:16