wrap cpp variant as dll for c to use

发布于:2025-08-15 ⋅ 阅读:(10) ⋅ 点赞:(0)

包装c++的variant给c用

variant_wrapper.cpp

#include <variant>
#include <unordered_map>
#include <cstring>
#include <cstdio>
#include <new>
#include <memory>
#include <functional>
#include <cstdlib>

// 类型ID定义
enum TypeId {
    TYPE_INVALID = -1,
    TYPE_INT = 0,
    TYPE_FLOAT = 1,
    TYPE_DOUBLE = 2,
    TYPE_STR = 3,
    TYPE_CUSTOM_BASE = 100
};

struct CustomTypeOps {
    size_t size;
    void (*copy)(const void* src, void* dest);
    void (*destroy)(void* data);
};

static std::unordered_map<TypeId, CustomTypeOps> g_type_registry;
static int g_next_custom_type = TYPE_CUSTOM_BASE;

extern "C" TypeId cvariant_register_custom_type(size_t size, 
                                              void (*copy)(const void*, void*),
                                              void (*destroy)(void*)) {
    TypeId id = static_cast<TypeId>(g_next_custom_type++);
    g_type_registry[id] = {size, copy, destroy};
    return id;
}

// 变体数据存储(字符串使用char*并手动管理内存)
using VariantData = std::variant<
    int,
    float,
    double,
    char*,  // 改为char*以存储动态分配的字符串
    std::unique_ptr<void, std::function<void(void*)>>
>;

typedef struct CVariant {
    VariantData data;
    TypeId type_id;
} CVariant;

static const CustomTypeOps* get_custom_ops(TypeId id) {
    auto it = g_type_registry.find(id);
    return (it != g_type_registry.end()) ? &it->second : nullptr;
}

extern "C" {
    CVariant* cvariant_create() {
        try {
            return new CVariant{{}, TYPE_INVALID};
        } catch (const std::bad_alloc&) {
            return nullptr;
        }
    }

    void cvariant_destroy(CVariant* var) {
        if (!var) return;
        
        // 关键修复:释放字符串内存
        if (var->type_id == TYPE_STR) {
            if (std::holds_alternative<char*>(var->data)) {
                char* str = std::get<char*>(var->data);
                free(str);  // 释放动态分配的字符串
            }
        }
        delete var;
    }

    void cvariant_set_int(CVariant* var, int value) {
        if (var) {
            // 清理原有字符串
            if (var->type_id == TYPE_STR && std::holds_alternative<char*>(var->data)) {
                free(std::get<char*>(var->data));
            }
            var->data = value;
            var->type_id = TYPE_INT;
        }
    }

    void cvariant_set_float(CVariant* var, float value) {
        if (var) {
            // 清理原有字符串
            if (var->type_id == TYPE_STR && std::holds_alternative<char*>(var->data)) {
                free(std::get<char*>(var->data));
            }
            var->data = value;
            var->type_id = TYPE_FLOAT;
        }
    }

    void cvariant_set_double(CVariant* var, double value) {
        if (var) {
            // 清理原有字符串
            if (var->type_id == TYPE_STR && std::holds_alternative<char*>(var->data)) {
                free(std::get<char*>(var->data));
            }
            var->data = value;
            var->type_id = TYPE_DOUBLE;
        }
    }

    // 关键修复:字符串存储改为动态分配
    void cvariant_set_str(CVariant* var, const char* value) {
        if (var) {
            // 先释放原有字符串
            if (var->type_id == TYPE_STR && std::holds_alternative<char*>(var->data)) {
                free(std::get<char*>(var->data));
            }
            
            // 复制字符串并存储
            if (value) {
                char* str = (char*)malloc(strlen(value) + 1);
                if (str) {
                    strcpy(str, value);
                    var->data = str;
                    var->type_id = TYPE_STR;
                    return;
                }
            }
            // 处理空字符串
            var->data = (char*)nullptr;
            var->type_id = TYPE_STR;
        }
    }

    int cvariant_set_custom(CVariant* var, TypeId type_id, const void* data) {
        if (!var || !data || type_id < TYPE_CUSTOM_BASE) return -1;
        
        // 清理原有字符串
        if (var->type_id == TYPE_STR && std::holds_alternative<char*>(var->data)) {
            free(std::get<char*>(var->data));
        }
        
        const auto* ops = get_custom_ops(type_id);
        if (!ops) return -1;

        void* storage = malloc(ops->size);
        if (!storage) return -1;
        ops->copy(data, storage);

        var->data = std::unique_ptr<void, std::function<void(void*)>>(
            storage,
            [type_id](void* ptr) {
                const auto* ops = get_custom_ops(type_id);
                if (ops) ops->destroy(ptr);
                free(ptr);
            }
        );
        var->type_id = type_id;
        return 0;
    }

    TypeId cvariant_get_type(const CVariant* var) {
        return var ? var->type_id : TYPE_INVALID;
    }

    int cvariant_get_int(const CVariant* var) {
        if (var && var->type_id == TYPE_INT && std::holds_alternative<int>(var->data)) {
            return std::get<int>(var->data);
        }
        fprintf(stderr, "cvariant: 类型错误(预期int)\n");
        return 0;
    }

    float cvariant_get_float(const CVariant* var) {
        if (var && var->type_id == TYPE_FLOAT && std::holds_alternative<float>(var->data)) {
            return std::get<float>(var->data);
        }
        fprintf(stderr, "cvariant: 类型错误(预期float)\n");
        return 0.0f;
    }

    double cvariant_get_double(const CVariant* var) {
        if (var && var->type_id == TYPE_DOUBLE && std::holds_alternative<double>(var->data)) {
            return std::get<double>(var->data);
        }
        fprintf(stderr, "cvariant: 类型错误(预期double)\n");
        return 0.0;
    }

    const char* cvariant_get_str(const CVariant* var) {
        if (var && var->type_id == TYPE_STR && std::holds_alternative<char*>(var->data)) {
            return std::get<char*>(var->data);
        }
        fprintf(stderr, "cvariant: 类型错误(预期字符串)\n");
        return nullptr;
    }

    int cvariant_get_custom(const CVariant* var, void* dest) {
        if (!var || !dest || var->type_id < TYPE_CUSTOM_BASE) return -1;
        
        const auto* ops = get_custom_ops(var->type_id);
        if (!ops) return -1;

        if (std::holds_alternative<std::unique_ptr<void, std::function<void(void*)>>>(var->data)) {
            const void* src = std::get<std::unique_ptr<void, std::function<void(void*)>>>(var->data).get();
            ops->copy(src, dest);
            return 0;
        }
        return -1;
    }
}

cvariant.h

#ifndef CVARIANT_H
#define CVARIANT_H

#include <stddef.h>

#ifdef __cplusplus
extern "C" {
#endif

// 类型ID(内置类型+自定义类型基值)
typedef enum {
    TYPE_INVALID = -1,
    TYPE_INT = 0,
    TYPE_FLOAT = 1,
    TYPE_DOUBLE = 2,
    TYPE_STR = 3,
    TYPE_CUSTOM_BASE = 100
} TypeId;

// 不透明结构体(隐藏C++实现)
typedef struct CVariant CVariant;

// 1. 核心管理函数
struct CVariant* cvariant_create();
void cvariant_destroy(struct CVariant* var);

// 2. 自定义类型注册(返回类型ID)
//  - size: 类型大小
//  - copy: 复制函数(src->dest)
//  - destroy: 销毁函数(释放内部资源)
TypeId cvariant_register_custom_type(size_t size,
                                   void (*copy)(const void* src, void* dest),
                                   void (*destroy)(void* data));

// 3. 设置值(内置类型)
void cvariant_set_int(struct CVariant* var, int value);
void cvariant_set_float(struct CVariant* var, float value);
void cvariant_set_double(struct CVariant* var, double value);
void cvariant_set_str(struct CVariant* var, const char* value);

// 4. 设置值(自定义类型)
//  - type_id: 注册时返回的类型ID
//  - data: 指向自定义类型数据的指针
int cvariant_set_custom(struct CVariant* var, TypeId type_id, const void* data);

// 5. 获取类型ID
TypeId cvariant_get_type(const struct CVariant* var);

// 6. 获取值(内置类型)
int cvariant_get_int(const struct CVariant* var);
float cvariant_get_float(const struct CVariant* var);
double cvariant_get_double(const struct CVariant* var);
const char* cvariant_get_str(const struct CVariant* var);

// 7. 获取值(自定义类型)
//  - dest: 用于接收数据的缓冲区(需提前分配足够空间)
int cvariant_get_custom(const struct CVariant* var, void* dest);

#ifdef __cplusplus
}
#endif

#endif // CVARIANT_H

build shared lib

g++ -shared -fPIC variant_wrapper.cpp -o cvariant.dll -Wl,--out-implib=libcvariant.a

conffget.c

#include "cvariant.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

// 手动实现strndup以兼容Windows平台
static char* strndup(const char* s, size_t n) {
    if (s == NULL) return NULL;
    
    // 计算实际需要复制的长度(不超过n且不超过原字符串长度)
    size_t len = strlen(s);
    if (n < len) len = n;
    
    // 分配内存(+1用于存储终止符)
    char* result = (char*)malloc(len + 1);
    if (result == NULL) return NULL;
    
    // 复制字符串并添加终止符
    memcpy(result, s, len);
    result[len] = '\0';
    return result;
}

// 配置项节点(存储键值对)
typedef struct ConfigNode {
    char* section;         // 节名(如"server")
    char* key;             // 键名(如"port")
    CVariant* value;       // 值(多类型存储)
    struct ConfigNode* next; // 链表下一个节点
} ConfigNode;

// 解析上下文
typedef struct {
    ConfigNode* head;      // 配置项链表头
    char* current_section; // 当前解析的节名
} ConfigParser;

// 初始化解析器
static ConfigParser* parser_init() {
    ConfigParser* parser = (ConfigParser*)malloc(sizeof(ConfigParser));
    parser->head = NULL;
    parser->current_section = NULL;
    return parser;
}

// 释放解析器资源
static void parser_free(ConfigParser* parser) {
    ConfigNode* node = parser->head;
    while (node) {
        ConfigNode* next = node->next;
        free(node->section);
        free(node->key);
        cvariant_destroy(node->value);
        free(node);
        node = next;
    }
    free(parser->current_section);
    free(parser);
}

// 去除字符串首尾空格
static char* trim(char* str) {
    if (!str) return NULL;
    // 去除开头空格
    while (isspace((unsigned char)*str)) str++;
    // 去除结尾空格
    if (*str) {
        char* end = str + strlen(str) - 1;
        while (end > str && isspace((unsigned char)*end)) end--;
        *(end + 1) = '\0';
    }
    return str;
}

// 识别值类型并存储到variant
static void set_value_by_type(CVariant* var, const char* value_str) {
    char* endptr;
    // 尝试识别为布尔值
    if (strcmp(value_str, "true") == 0 || strcmp(value_str, "yes") == 0) {
        cvariant_set_int(var, 1); // 1表示true
        return;
    }
    if (strcmp(value_str, "false") == 0 || strcmp(value_str, "no") == 0) {
        cvariant_set_int(var, 0); // 0表示false
        return;
    }
    // 尝试识别为整数
    long int_val = strtol(value_str, &endptr, 10);
    if (*endptr == '\0') {
        cvariant_set_int(var, (int)int_val);
        return;
    }
    // 尝试识别为浮点数
    double float_val = strtod(value_str, &endptr);
    if (*endptr == '\0') {
        cvariant_set_double(var, float_val);
        return;
    }
    // 尝试识别为带引号的字符串(去除引号)
    if (value_str[0] == '"' && value_str[strlen(value_str)-1] == '"') {
        char* str_val = strndup(value_str + 1, strlen(value_str) - 2);
        cvariant_set_str(var, str_val);
        free(str_val);
        return;
    }
    // 否则视为普通字符串
    cvariant_set_str(var, value_str);
}

// 添加配置项到链表
static void add_config_node(ConfigParser* parser, const char* key, const char* value) {
    if (!parser->current_section || !key || !value) return;

    ConfigNode* node = (ConfigNode*)malloc(sizeof(ConfigNode));
    node->section = strdup(parser->current_section);
    node->key = strdup(key);
    node->value = cvariant_create();
    set_value_by_type(node->value, value); // 自动识别类型
    node->next = parser->head;
    parser->head = node;
}

// 解析INI文件
static int parse_ini_file(ConfigParser* parser, const char* filename) {
    FILE* f = fopen(filename, "r");
    if (!f) {
        fprintf(stderr, "无法打开文件: %s\n", filename);
        return -1;
    }

    char line[1024];
    int line_num = 0;
    while (fgets(line, sizeof(line), f)) {
        line_num++;
        char* content = trim(line);
        // 跳过空行和注释
        if (*content == '\0' || *content == ';' || *content == '#') continue;
        // 解析节名(如[server])
        if (*content == '[' && content[strlen(content)-1] == ']') {
            free(parser->current_section);
            parser->current_section = strndup(content + 1, strlen(content) - 2);
            continue;
        }
        // 解析键值对(如port=8080)
        char* eq_pos = strchr(content, '=');
        if (eq_pos) {
            *eq_pos = '\0';
            char* key = trim(content);
            char* value = trim(eq_pos + 1);
            add_config_node(parser, key, value);
        } else {
            fprintf(stderr, "警告: 无效行 %d: %s\n", line_num, content);
        }
    }
    fclose(f);
    return 0;
}

// 查询配置项
static int query_config(ConfigParser* parser, const char* query) {
    // 拆分查询为节名和键名(格式:section.key)
    char* dot_pos = strchr(query, '.');
    if (!dot_pos) {
        fprintf(stderr, "查询格式错误,应为: 节名.键名\n");
        return -1;
    }
    char* section = strndup(query, dot_pos - query);
    char* key = strdup(dot_pos + 1);

    // 遍历链表查找配置项
    ConfigNode* node = parser->head;
    while (node) {
        if (strcmp(node->section, section) == 0 && strcmp(node->key, key) == 0) {
            // 根据类型输出值
            switch (cvariant_get_type(node->value)) {
                case TYPE_INT:
                    // 布尔值特殊处理
                    if (strcmp(key, "enable") == 0 || strcmp(key, "active") == 0) {
                        printf("%s\n", cvariant_get_int(node->value) ? "true" : "false");
                    } else {
                        printf("%d\n", cvariant_get_int(node->value));
                    }
                    break;
                case TYPE_DOUBLE:
                    printf("%g\n", cvariant_get_double(node->value));
                    break;
                case TYPE_STR:
                    printf("%s\n", cvariant_get_str(node->value));
                    break;
                default:
                    printf("未知类型\n");
            }
            free(section);
            free(key);
            return 0;
        }
        node = node->next;
    }

    fprintf(stderr, "未找到配置项: %s\n", query);
    free(section);
    free(key);
    return -1;
}

// 列出所有配置项
static void list_all_configs(ConfigParser* parser) {
    ConfigNode* node = parser->head;
    while (node) {
        printf("[%s] %s = ", node->section, node->key);
        // 根据类型输出值
        switch (cvariant_get_type(node->value)) {
            case TYPE_INT:
                printf("%d (int)\n", cvariant_get_int(node->value));
                break;
            case TYPE_DOUBLE:
                printf("%g (float)\n", cvariant_get_double(node->value));
                break;
            case TYPE_STR:
                printf("%s (string)\n", cvariant_get_str(node->value));
                break;
        }
        node = node->next;
    }
}

// 显示帮助
static void print_help(const char* progname) {
    printf("用法: %s [选项] <INI文件> [查询]\n", progname);
    printf("解析INI配置文件并查询值(兼容Linux风格)\n");
    printf("选项:\n");
    printf("  -l        列出文件中所有配置项及类型\n");
    printf("  -h        显示帮助信息\n");
    printf("查询格式: 节名.键名(如 'server.port')\n");
    printf("示例:\n");
    printf("  %s config.ini server.port      # 查询[server]节的port值\n", progname);
    printf("  %s -l app.ini                 # 列出app.ini所有配置项\n", progname);
    printf("  %s settings.ini log.enable    # 查询[log]节的enable值(布尔型)\n", progname);
}

int main(int argc, char* argv[]) {
    if (argc < 2) {
        print_help(argv[0]);
        return 1;
    }

    int list_mode = 0;
    const char* filename = NULL;
    const char* query = NULL;

    // 解析命令行参数
    if (strcmp(argv[1], "-h") == 0) {
        print_help(argv[0]);
        return 0;
    } else if (strcmp(argv[1], "-l") == 0) {
        if (argc < 3) {
            print_help(argv[0]);
            return 1;
        }
        list_mode = 1;
        filename = argv[2];
    } else {
        filename = argv[1];
        query = (argc >= 3) ? argv[2] : NULL;
        if (!query) {
            print_help(argv[0]);
            return 1;
        }
    }

    // 解析配置文件
    ConfigParser* parser = parser_init();
    if (parse_ini_file(parser, filename) != 0) {
        parser_free(parser);
        return 1;
    }

    // 执行操作
    if (list_mode) {
        list_all_configs(parser);
    } else {
        query_config(parser, query);
    }

    // 清理资源
    parser_free(parser);
    return 0;
}

build confget.c

gcc -o confget.exe confget.c -L . -lcvariant

config.ini

; 示例配置文件
[server]
port = 8080
host = "localhost"
timeout = 30.5
enable = true

[log]
path = "C:\logs"
level = info
max_size = 1024

sample output

# 查询[server]节的port(整数)
confget.exe config.ini server.port
# 输出:8080

# 查询[server]节的timeout(浮点数)
confget.exe config.ini server.timeout
# 输出:30.5

# 查询[server]节的enable(布尔值)
confget.exe config.ini server.enable
# 输出:true

# 查询[log]节的path(字符串)
confget.exe config.ini log.path
# 输出:localhost

# 列出所有配置项及类型
confget.exe -l config.ini
# 输出:
# [log] max_size = 1024 (int)
# [log] level = info (string)
# [log] path = C:\logs (string)
# [server] enable = 1 (int)
# [server] timeout = 30.5 (float)
# [server] host = localhost (string)
# [server] port = 8080 (int)

probe1.c

#include "cvariant.h"
#include <stdio.h>
#include <string.h>

// 自定义类型定义(见上文)
typedef struct { int x; int y; char name[32]; } Point;
static void point_copy(const void* src, void* dest);
static void point_destroy(void* data);

int main() {
    // 1. 注册自定义类型(获取类型ID)
    TypeId point_type = cvariant_register_custom_type(
        sizeof(Point),
        point_copy,
        point_destroy
    );
    printf("注册自定义类型 Point,ID: %d\n", point_type);

    // 2. 创建变体对象
    struct CVariant* var = cvariant_create();
    if (!var) {
        printf("创建变体失败\n");
        return 1;
    }

    // 3. 测试内置类型
    cvariant_set_int(var, 123);
    printf("类型: %d (预期0), 值: %d\n", cvariant_get_type(var), cvariant_get_int(var));

    cvariant_set_double(var, 3.1415926535);
    printf("类型: %d (预期2), 值: %lf\n", cvariant_get_type(var), cvariant_get_double(var));

    cvariant_set_str(var, "测试字符串");
    printf("类型: %d (预期3), 值: %s\n", cvariant_get_type(var), cvariant_get_str(var));

    // 4. 测试自定义类型(Point)
    Point p = {10, 20, "原点"};
    cvariant_set_custom(var, point_type, &p);
    
    if (cvariant_get_type(var) == point_type) {
        Point p_out;
        cvariant_get_custom(var, &p_out);
        printf("类型: %d (预期自定义ID), 值: (%d, %d, %s)\n",
               cvariant_get_type(var), p_out.x, p_out.y, p_out.name);
    }

    // 5. 清理
    cvariant_destroy(var);
    return 0;
}

// 实现自定义类型的复制和销毁函数
static void point_copy(const void* src, void* dest) {
    const Point* s = (const Point*)src;
    Point* d = (Point*)dest;
    d->x = s->x;
    d->y = s->y;
    strncpy(d->name, s->name, sizeof(d->name)-1);
}

static void point_destroy(void* data) {
    // 示例:无动态内存需要释放
}

probe2.c

#include "cvariant.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// 1. 定义枚举类型(颜色)
typedef enum {
    RED,
    GREEN,
    BLUE,
    BLACK,
    WHITE
} Color;

// 2. 定义联合体类型(通用数值)
typedef union {
    int i;
    float f;
    double d;
} Number;

// 3. 定义包含枚举和联合体的复杂结构体
typedef struct {
    Color color;       // 枚举成员
    Number value;      // 联合体成员
    char name[64];     // 字符串成员
} ComplexData;

// ------------------------------
// 枚举类型(Color)的操作函数
// ------------------------------
static void color_copy(const void* src, void* dest) {
    // 枚举本质是整数,直接复制内存
    *(Color*)dest = *(const Color*)src;
}

static void color_destroy(void* data) {
    // 枚举无动态内存,无需额外操作
}

// ------------------------------
// 联合体类型(Number)的操作函数
// ------------------------------
static void number_copy(const void* src, void* dest) {
    // 联合体整体复制
    memcpy(dest, src, sizeof(Number));
}

static void number_destroy(void* data) {
    // 联合体无动态内存,无需额外操作
}

// ------------------------------
// 复杂结构体(ComplexData)的操作函数
// ------------------------------
static void complexdata_copy(const void* src, void* dest) {
    const ComplexData* s = (const ComplexData*)src;
    ComplexData* d = (ComplexData*)dest;
    
    // 分别复制成员(枚举+联合体+字符串)
    d->color = s->color;
    d->value = s->value;  // 联合体直接复制
    strncpy(d->name, s->name, sizeof(d->name)-1);
}

static void complexdata_destroy(void* data) {
    // 若结构体包含动态内存(如malloc的指针),需在此释放
    // 本示例无动态内存,仅作演示
}

int main() {
    // 1. 注册自定义类型(获取类型ID)
    TypeId color_type = cvariant_register_custom_type(
        sizeof(Color), color_copy, color_destroy
    );
    TypeId number_type = cvariant_register_custom_type(
        sizeof(Number), number_copy, number_destroy
    );
    TypeId complex_type = cvariant_register_custom_type(
        sizeof(ComplexData), complexdata_copy, complexdata_destroy
    );

    printf("注册类型ID:\n");
    printf("  Color: %d\n", color_type);
    printf("  Number: %d\n", number_type);
    printf("  ComplexData: %d\n\n", complex_type);

    // 2. 创建变体对象
    struct CVariant* var = cvariant_create();
    if (!var) {
        fprintf(stderr, "创建变体失败\n");
        return 1;
    }

    // 3. 测试枚举类型(Color)
    Color my_color = BLUE;
    cvariant_set_custom(var, color_type, &my_color);
    
    if (cvariant_get_type(var) == color_type) {
        Color get_color;
        cvariant_get_custom(var, &get_color);
        printf("枚举类型测试:\n");
        printf("  存储的颜色: %d (BLUE对应值为2)\n", get_color);
    }

    // 4. 测试联合体类型(Number)
    Number my_num;
    my_num.f = 3.14159f;  // 存储float值
    cvariant_set_custom(var, number_type, &my_num);
    
    if (cvariant_get_type(var) == number_type) {
        Number get_num;
        cvariant_get_custom(var, &get_num);
        printf("\n联合体类型测试:\n");
        printf("  存储的float值: %f\n", get_num.f);
    }

    // 5. 测试复杂结构体(包含枚举和联合体)
    ComplexData my_complex = {
        .color = GREEN,
        .value = {.d = 99.99},  // 联合体存储double
        .name = "示例数据"
    };
    cvariant_set_custom(var, complex_type, &my_complex);
    
    if (cvariant_get_type(var) == complex_type) {
        ComplexData get_complex;
        cvariant_get_custom(var, &get_complex);
        printf("\n复杂结构体测试:\n");
        printf("  颜色枚举值: %d (GREEN对应值为1)\n", get_complex.color);
        printf("  联合体double值: %lf\n", get_complex.value.d);
        printf("  名称: %s\n", get_complex.name);
    }

    // 6. 清理资源
    cvariant_destroy(var);
    return 0;
}

probe3.c

#include "cvariant.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// 带动态内存的结构体(需要手动释放)
typedef struct {
    int id;
    char* name;  // 动态分配的字符串(需malloc/free)
    float score;
} DynamicData;


// 复制函数:深度复制动态内存
static void dynamicdata_copy(const void* src, void* dest) {
    const DynamicData* s = (const DynamicData*)src;
    DynamicData* d = (DynamicData*)dest;

    // 复制基础类型
    d->id = s->id;
    d->score = s->score;

    // 复制动态字符串(关键:手动分配新内存)
    if (s->name) {
        d->name = (char*)malloc(strlen(s->name) + 1);  // 分配内存
        strcpy(d->name, s->name);  // 复制内容
    } else {
        d->name = NULL;
    }
}

// 销毁函数:释放动态内存(关键:防止内存泄漏)
static void dynamicdata_destroy(void* data) {
    DynamicData* d = (DynamicData*)data;
    if (d->name) {
        free(d->name);  // 释放动态字符串
        d->name = NULL;  // 避免野指针
    }
}

int main() {
    // 1. 注册自定义类型(带动态内存)
    TypeId dynamic_type = cvariant_register_custom_type(
        sizeof(DynamicData),
        dynamicdata_copy,    // 深度复制动态内存
        dynamicdata_destroy  // 释放动态内存
    );
    printf("注册动态类型 ID: %d\n", dynamic_type);

    // 2. 创建原始数据(带动态内存)
    DynamicData original;
    original.id = 1001;
    original.name = (char*)malloc(strlen("Alice") + 1);  // 手动分配
    strcpy(original.name, "Alice");
    original.score = 95.5f;
    printf("原始数据: id=%d, name=%s, score=%.1f\n", 
           original.id, original.name, original.score);

    // 3. 用变体类型存储动态数据
    struct CVariant* var = cvariant_create();
    cvariant_set_custom(var, dynamic_type, &original);

    // 4. 从变体中读取数据(验证复制是否正确)
    if (cvariant_get_type(var) == dynamic_type) {
        DynamicData copy;
        cvariant_get_custom(var, &copy);
        printf("从变体读取: id=%d, name=%s, score=%.1f\n",
               copy.id, copy.name, copy.score);
    }

    // 5. 清理资源
    // 注意:原始数据的动态内存需要手动释放(变体内部的由destroy处理)
    free(original.name);  // 释放原始数据的name
    cvariant_destroy(var);  // 变体销毁时会自动调用dynamicdata_destroy

    return 0;
}

网站公告

今日签到

点亮在社区的每一天
去签到