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

如何让宏定义支持字符串、整数、布尔输入并解决C4047错误

解决Lua表读取宏的C4047类型不匹配错误

问题背景

需要实现一个能读取Lua表中字符串、整数、布尔类型元素的C宏,当前代码触发C4047错误:'char *' differs in levels of indirection from 'int'。

关联代码

Lua表定义(table.lua):

Strings = {
  Apply = {"successfully applied", true, 150, "OK" },
  Check = {"check done", 100, false },
  Test  = {"test completed", "Fail", 1, true }
};

原C语言宏及调用代码:

#define lua_get_test(L, tbl, ...) do { \
    lua_getfield(L, lua_gettop(L), tbl); \
    if (lua_istable(L, lua_gettop(L))) \
    { \
        int n = (int)lua_rawlen(L, lua_gettop(L)); \
        for (int i = 1; i <= n; i++) { \
            lua_rawgeti(L, lua_gettop(L), i); \
            if (lua_isstring(L, lua_gettop(L))) \
                strcpy(__VA_ARGS__, lua_tostring(L, lua_gettop(L))); \
            else if(lua_isboolean(L, lua_gettop(L))) \
                __VA_ARGS__ = lua_toboolean(L, lua_gettop(L)); \
            else if(lua_isinteger(L, lua_gettop(L))) \
                __VA_ARGS__ = (int)lua_tointeger(L, lua_gettop(L)); \
            else \
                continue; \
            lua_pop(L, 1); \
        } \
    } \
    lua_pop(L, 1); \
} while(false)

void read_table(void) {
    lua_State *L;
    L = luaL_newstate();
    luaL_openlibs(L);

    if (luaL_loadfile(L, "table.lua") || lua_pcall(L, 0, 0, 0))
    {
        ShowError("Error reading 'table.lua'\n");
        return;
    }

    lua_getglobal(L, "Strings");
    lua_get_test(L, "Apply", var_string, var_bool, var_int, var_string);
    lua_get_test(L, "Check", var_string, var_int, var_bool);
    lua_get_test(L, "Test", var_string, var_string, var_int, var_bool);

    lua_close(L);
    printf("Read Table complete.\n");

}

错误原因

  1. 可变参数处理逻辑错误:原宏循环中直接对__VA_ARGS__执行赋值操作,相当于同时给所有传入的变量执行同一操作(比如给int变量调用strcpy),导致类型不匹配。
  2. 缺乏类型匹配机制:宏无法自动识别每个变量的类型,强行统一处理必然触发类型转换错误。

解决方案

核心思路

  • 用C11的_Generic关键字实现类型匹配,根据目标变量类型自动选择对应的Lua读取逻辑。
  • 拆分宏为对应参数个数的版本,确保每个变量对应Lua表中指定位置的元素,逐个处理避免批量赋值错误。

修正后的代码

#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>

void ShowError(const char* msg) {
    fprintf(stderr, "%s", msg);
}

// 辅助宏:根据目标变量类型读取单个Lua表元素
#define LUA_READ_ONE(L, idx, var) do { \
    lua_rawgeti(L, -1, idx); \
    _Generic((var), \
        char*: strcpy(var, lua_tostring(L, -1)), \
        int: (var = (int)lua_tointeger(L, -1)), \
        bool: (var = lua_toboolean(L, -1)) \
    ); \
    lua_pop(L, 1); \
} while(false)

// 读取含4个元素的Lua表
#define lua_read_4(L, tbl, v1, v2, v3, v4) do { \
    lua_getfield(L, -1, tbl); \
    if (lua_istable(L, -1)) { \
        LUA_READ_ONE(L, 1, v1); \
        LUA_READ_ONE(L, 2, v2); \
        LUA_READ_ONE(L, 3, v3); \
        LUA_READ_ONE(L, 4, v4); \
    } \
    lua_pop(L, 1); \
} while(false)

// 读取含3个元素的Lua表
#define lua_read_3(L, tbl, v1, v2, v3) do { \
    lua_getfield(L, -1, tbl); \
    if (lua_istable(L, -1)) { \
        LUA_READ_ONE(L, 1, v1); \
        LUA_READ_ONE(L, 2, v2); \
        LUA_READ_ONE(L, 3, v3); \
    } \
    lua_pop(L, 1); \
} while(false)

void read_table(void) {
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);

    if (luaL_loadfile(L, "table.lua") || lua_pcall(L, 0, 0, 0)) {
        ShowError("Error reading 'table.lua'\n");
        lua_close(L);
        return;
    }

    lua_getglobal(L, "Strings");

    // 读取Apply表
    char apply_str1[100], apply_str2[100];
    bool apply_bool;
    int apply_int;
    lua_read_4(L, "Apply", apply_str1, apply_bool, apply_int, apply_str2);

    // 读取Check表
    char check_str[100];
    int check_int;
    bool check_bool;
    lua_read_3(L, "Check", check_str, check_int, check_bool);

    // 读取Test表
    char test_str1[100], test_str2[100];
    int test_int;
    bool test_bool;
    lua_read_4(L, "Test", test_str1, test_str2, test_int, test_bool);

    // 验证读取结果
    printf("Apply: %s, %d, %d, %s\n", apply_str1, apply_bool, apply_int, apply_str2);
    printf("Check: %s, %d, %d\n", check_str, check_int, check_bool);
    printf("Test: %s, %s, %d, %d\n", test_str1, test_str2, test_int, test_bool);

    lua_close(L);
    printf("Read Table complete.\n");
}

int main() {
    read_table();
    return 0;
}

说明

  • _Generic关键字会根据目标变量的类型,自动选择对应的赋值逻辑,确保类型匹配。
  • 针对不同元素个数的Lua表定义专用宏(lua_read_3、lua_read_4),保证每个变量对应表中指定位置的元素,避免批量赋值的类型错误。
  • 辅助宏LUA_READ_ONE封装单个元素的读取逻辑,简化代码复用。

内容的提问来源于stack exchange,提问作者Michael

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 12:40:53