包装c++的variant给c用
variant_wrapper.cpp
# include <variant>
# include <unordered_map>
# include <cstring>
# include <cstdio>
# include <new>
# include <memory>
# include <functional>
# include <cstdlib>
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;
}
using VariantData = std:: variant< int , float , double , 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
typedef enum { TYPE_INVALID = - 1 , TYPE_INT = 0 , TYPE_FLOAT = 1 , TYPE_DOUBLE = 2 , TYPE_STR = 3 , TYPE_CUSTOM_BASE = 100
} TypeId;
typedef struct CVariant CVariant;
struct CVariant * cvariant_create ( ) ;
void cvariant_destroy ( struct CVariant * var) ;
TypeId cvariant_register_custom_type ( size_t size, void ( * copy) ( const void * src, void * dest) , void ( * destroy) ( void * data) ) ;
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) ;
int cvariant_set_custom ( struct CVariant * var, TypeId type_id, const void * data) ;
TypeId cvariant_get_type ( const struct CVariant * var) ;
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) ;
int cvariant_get_custom ( const struct CVariant * var, void * dest) ; # ifdef __cplusplus
}
# endif # endif
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>
static char * strndup ( const char * s, size_t n) { if ( s == NULL ) return NULL ; size_t len = strlen ( s) ; if ( n < len) len = n; 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; char * key; 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;
}
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 ) ; return ; } if ( strcmp ( value_str, "false" ) == 0 || strcmp ( value_str, "no" ) == 0 ) { cvariant_set_int ( var, 0 ) ; 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;
}
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 ; if ( * content == '[' && content[ strlen ( content) - 1 ] == ']' ) { free ( parser-> current_section) ; parser-> current_section = strndup ( content + 1 , strlen ( content) - 2 ) ; continue ; } 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) { 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
confget.exe config.ini server.port
confget.exe config.ini server.timeout
confget.exe config.ini server.enable
confget.exe config.ini log.path
confget.exe -l config.ini
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 ( ) { TypeId point_type = cvariant_register_custom_type ( sizeof ( Point) , point_copy, point_destroy) ; printf ( "注册自定义类型 Point,ID: %d\n" , point_type) ; struct CVariant * var = cvariant_create ( ) ; if ( ! var) { printf ( "创建变体失败\n" ) ; return 1 ; } 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) ) ; 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) ; } 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>
typedef enum { RED, GREEN, BLUE, BLACK, WHITE
} Color;
typedef union { int i; float f; double d;
} Number;
typedef struct { Color color; Number value; char name[ 64 ] ;
} ComplexData;
static void color_copy ( const void * src, void * dest) { * ( Color* ) dest = * ( const Color* ) src;
} static void color_destroy ( void * data) {
}
static void number_copy ( const void * src, void * dest) { memcpy ( dest, src, sizeof ( Number) ) ;
} static void number_destroy ( void * data) {
}
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) {
} int main ( ) { 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) ; struct CVariant * var = cvariant_create ( ) ; if ( ! var) { fprintf ( stderr , "创建变体失败\n" ) ; return 1 ; } 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) ; } Number my_num; my_num. f = 3.14159f ; 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) ; } ComplexData my_complex = { . color = GREEN, . value = { . d = 99.99 } , . 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) ; } 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; 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 ( ) { TypeId dynamic_type = cvariant_register_custom_type ( sizeof ( DynamicData) , dynamicdata_copy, dynamicdata_destroy ) ; printf ( "注册动态类型 ID: %d\n" , dynamic_type) ; 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) ; struct CVariant * var = cvariant_create ( ) ; cvariant_set_custom ( var, dynamic_type, & original) ; 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) ; } free ( original. name) ; cvariant_destroy ( var) ; return 0 ;
}