You need to enable JavaScript to run this app. C语言中如何将结构体act函数指针转为对应函数名的字符串
优惠活动
大模型
产品
解决方案
定价
更多

C语言中如何将结构体act函数指针转为对应函数名的字符串

报错原因

之前的写法触发stray '#'错误,本质是对#预处理运算符的使用规则理解偏差:

  • #是仅在预处理阶段生效的字符串化操作符,合法使用场景仅限宏定义内部、作用于宏的形参,不允许出现在普通业务代码的位置。
  • 代码中写的#(m->act)既不属于宏定义内的合法语法,对应的值也是运行时才能确定的结构体成员,预处理阶段根本无法得知m->act最终指向哪个函数,自然无法完成字符串化。
  • 哪怕直接在普通代码行里写#cgi_ml_schema,也会触发同样的语法错误,和表达式无关,纯粹是#的位置不符合语法要求。
可行实现方案

方案1:静态结构体同步存储函数名(最适配当前场景)

你现有的cgi_machine_learning_handlers是完全静态初始化的数组,无动态运行时逻辑,最适合通过宏定义把函数名在编译期同步生成字符串,零运行时开销。
实现步骤:

  • 给cgi_object_t结构体增加一个用于存储函数名字符串的成员,比如const char *act_name;
  • 定义批量初始化的宏,利用#的合法使用场景完成字符串化,避免手动重复维护函数名和字符串两份内容:
// 宏定义,统一初始化handler项,自动生成函数名字符串
#define CGI_ML_HANDLER_INIT(path_val, act_func, ...) { \
    .path = path_val, \
    .grp = ACC_GRP_ML, \
    .r_vdom = VDOM_PER_VDOM, \
    .r_global = VDOM_PER_VDOM, \
    .act = act_func, \
    .act_name = #act_func, \
    .flags = API_FLAG_NO_SCHEMA, \
    ##__VA_ARGS__ \
}

// 原数组定义简化后直接调用宏,无重复维护成本
cgi_object_t cgi_machine_learning_handlers[] =
{
    CGI_ML_HANDLER_INIT("schema", cgi_ml_schema),
    CGI_ML_HANDLER_INIT("policy.svmattacktypes", cgi_ml_policy_svmattacktypes_get),
    // 新增其他handler项时直接按格式填即可,act_name会自动生成
};
  • 后续获取函数名时,直接读取当前遍历元素的act_name成员即可,不需要任何额外计算:
// 遍历handler数组时直接取值使用
const char *current_act_name = m->act_name;
json_object_object_get(request, current_act_name);

方案2:静态函数指针映射表

如果不方便修改cgi_object_t的结构体定义,也可以在编译期建立函数指针和对应字符串的映射表,运行时通过指针匹配查找对应名称:

// 静态映射表,和handler数组的act成员保持一一对应
static const struct {
    cgi_act_handler_t func_ptr;
    const char *func_name;
} act_name_map[] = {
    {cgi_ml_schema, "cgi_ml_schema"},
    {cgi_ml_policy_svmattacktypes_get, "cgi_ml_policy_svmattacktypes_get"},
};

// 封装查找函数
const char *get_act_name(cgi_act_handler_t act) {
    for (int i = 0; i < sizeof(act_name_map)/sizeof(act_name_map[0]); i++) {
        if (act_name_map[i].func_ptr == act) {
            return act_name_map[i].func_name;
        }
    }
    return NULL;
}

// 实际使用时传入当前m->act即可获取字符串
const char *var = json_object_object_get(request, get_act_name(m->act));

注意:这个方案的维护成本更高,每新增一个handler项,都需要同步在映射表中追加一项,很容易出现漏改。

方案3:动态符号解析(不推荐用于当前场景)

可以借助系统动态链接器的能力,通过函数指针反向查询对应的符号名(比如Linux下的dladdr、Windows下的GetProcAddress),但这种方案:

  • 需要额外配置编译选项导出所有静态函数的符号表(比如Linux下需要加-rdynamic编译参数)
  • 运行时开销远高于前面两种静态方案
  • 容易受程序打包、符号裁剪的影响出现查询失败,完全不适合这种固定的内部handler表场景。

内容的提问来源于stack exchange,提问作者ajfbiw.s

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.27 20:45:01