Melon 库使用指南 Melon 库使用指南目录一、概述二、安装与编译链接安装编译链接三、核心组件与函数签名详解数组 (mln_array.h)内存池 (mln_alloc.h)事件机制 (mln_event.h)日志 (mln_log.h)四、日常使用实例示例1内存池与数组结合使用示例2事件定时器五、任务编排综合实例多线程任务调度系统六、配置与调试七、最佳实践与常见问题最佳实践常见问题一、概述Melon 是一个跨平台的 C 语言基础开发库它以开箱即用、无第三方依赖为核心优势为开发者提供了从底层数据结构到上层应用框架的丰富组件。它支持C99 标准并集成了面向切面编程AOP等高级特性。其核心模块包括数据结构双向链表、红黑树、斐波那契堆、队列、数组、哈希表等。算法KMP、RSA、各类哈希、数据恢复算法等。框架多进程模型、多线程模型、事件机制、内存池、日志、IPC 等。脚本语言内置了名为Melang的协程脚本语言。二、安装与编译链接1. 安装Melon 的安装过程非常标准。在 Linux/macOS 环境下执行以下命令gitclone https://github.com/Water-Melon/Melon.gitcdMelon ./configure[--prefixYOUR_INSTALL_PATH]# 可指定安装路径默认 /usr/local/melonmakesudomakeinstall选择性编译Melon 支持模块化编译你可以在./configure阶段通过参数只选择你需要的组件以减小库体积。Windows 支持在 Windows 上需要在git bash或mingw环境中进行编译。2. 编译链接安装完成后编译你的程序时需要链接 Melon 库。gcc-oyour_program your_program.c-I/usr/local/melon/include/-L/usr/local/melon/lib/-lmelon-I指定头文件.h搜索路径。-L指定库文件.so或.a搜索路径。-lmelon链接 Melon 库。在 Windows 的git bash中命令略有不同gcc-otesttest.c-I$HOME/libmelon/include/-L$HOME/libmelon/lib/-llibmelon-lWs2_32三、核心组件与函数签名详解Melon 的每个功能模块都对应一个头文件使用时按需引入即可。1. 数组 (mln_array.h)Melon 提供了动态数组支持自动扩容。核心数据结构mln_array_tsize: 单个元素的字节大小。nalloc: 初始分配的元素个数后续按两倍扩容。nelts: 当前数组中元素的个数。关键函数int mln_array_init(mln_array_t *arr, array_free free, mln_size_t size, mln_size_t nalloc)初始化一个数组对象。arr: 数组对象指针。free: 释放数组中元素资源的回调函数指针。若元素无需特殊释放可传NULL。size: 单个元素的字节大小。nalloc: 初始数组长度。返回值成功返回0失败返回-1。void *mln_array_push(mln_array_t *arr)在数组末尾追加一个元素并返回指向新元素内存的指针。void *mln_array_pushn(mln_array_t *arr, mln_size_t n)追加n个元素并返回第一个元素的内存地址。void mln_array_pop(mln_array_t *arr)移除并释放数组末尾的元素。void mln_array_destroy(mln_array_t *arr)释放数组所有元素的内存。void mln_array_free(mln_array_t *arr)释放所有元素并释放数组结构体本身。2. 内存池 (mln_alloc.h)内存池能有效减少内存碎片提高分配效率。关键函数mln_alloc_t *mln_alloc_init(void *)创建一个内存池。参数通常传NULL。void *mln_alloc_m(mln_alloc_t *, mln_size_t size)从内存池中分配size字节的内存。void mln_alloc_free(void *)将内存释放回池中。void mln_alloc_destroy(mln_alloc_t *)销毁整个内存池。3. 事件机制 (mln_event.h)Melon 的事件机制封装了epoll/kqueue/select用于处理 I/O 和定时事件。关键函数mln_event_t *mln_event_new(void)创建一个新的事件结构。int mln_event_fd_set(mln_event_t *event, int fd, mln_u32_t flag, int timeout_ms, void *data, ev_fd_handler fd_handler)监听一个文件描述符fd的事件。flag: 事件类型如M_EV_RECV读、M_EV_SEND写可用|组合。timeout_ms: 超时时间M_EV_UNLIMITED表示永不超时。fd_handler: 事件触发时的回调函数。int mln_event_timer_set(mln_event_t *event, mln_u32_t msec, void *data, ev_tm_handler tm_handler)设置一个定时器。msec: 定时时长单位毫秒。tm_handler: 定时器触发的回调函数。注意定时器是一次性的触发后会自动从事件集中删除。如需重复触发需在回调函数中再次调用本函数。void mln_event_dispatch(mln_event_t *event)进入事件循环开始分发事件。4. 日志 (mln_log.h)Melon 的日志模块简单易用。关键宏mln_log(level, fmt, ...)输出日志。level: 日志级别如debug,info,warn,error,none。日志输出位置由配置文件中的log_path决定。四、日常使用实例示例1内存池与数组结合使用此示例演示了如何创建内存池并使用池化内存初始化一个动态数组。#includestdio.h#includemln_alloc.h#includemln_array.h// 数组元素的释放回调函数如果元素有动态资源需在此释放voidfree_element(void*element){// 本例中元素是 int无需特殊释放}intmain(intargc,char*argv[]){// 1. 创建内存池mln_alloc_t*poolmln_alloc_init(NULL);if(poolNULL){fprintf(stderr,Memory pool init failed.\n);return-1;}// 2. 使用内存池初始化数组mln_array_tarr;// 参数数组对象, 释放回调, 元素大小(int), 初始分配4个元素if(mln_array_pool_init(arr,free_element,sizeof(int),4,pool,(array_pool_alloc_handler)mln_alloc_m,(array_pool_free_handler)mln_alloc_free)0){fprintf(stderr,Array init failed.\n);mln_alloc_destroy(pool);return-1;}// 3. 向数组中添加元素for(inti0;i10;i){int*new_elem(int*)mln_array_push(arr);if(new_elemNULL){fprintf(stderr,Push element failed.\n);break;}*new_elemi*10;}// 4. 打印数组元素printf(Array elements: );for(inti0;iarr.nelts;i){printf(%d ,((int*)arr.ptr)[i]);// arr.ptr 指向数据区起始}printf(\n);// 5. 销毁数组释放元素内存mln_array_destroy(arr);// 6. 销毁内存池mln_alloc_destroy(pool);return0;}编译运行gcc-oarray_demo array_demo.c-I/usr/local/melon/include/-L/usr/local/melon/lib/-lmelon./array_demo示例2事件定时器此示例演示了如何使用 Melon 的事件机制创建一个每秒打印一次的定时器。#includestdio.h#includemln_event.h#includemln_log.hstaticvoidtimer_handler(mln_event_t*ev,void*data){staticintcount0;mln_log(debug,Timer triggered! Count: %d\n,count);// 重新设置定时器以实现周期性触发mln_event_timer_set(ev,1000,NULL,timer_handler);}intmain(intargc,char*argv[]){// 1. 创建事件结构mln_event_t*evmln_event_new();if(evNULL){fprintf(stderr,Event create failed.\n);return-1;}// 2. 设置定时器1秒后触发if(mln_event_timer_set(ev,1000,NULL,timer_handler)0){fprintf(stderr,Timer set failed.\n);mln_event_free(ev);return-1;}// 3. 进入事件循环会阻塞在这里mln_event_dispatch(ev);// 4. 清理资源通常不会执行到mln_event_free(ev);return0;}编译运行gcc-otimer_demo timer_demo.c-I/usr/local/melon/include/-L/usr/local/melon/lib/-lmelon./timer_demo五、任务编排综合实例多线程任务调度系统这个实例将构建一个更完整的系统展示 Melon 多线程框架、事件定时器、动态追踪mln_trace等特性的综合运用。系统将演示主线程如何动态地创建、监控和销毁工作线程。功能设计主线程作为管理者每隔一秒检查一次状态并根据状态sw开关决定是创建还是销毁一个名为 “worker” 的工作线程。工作线程 (“worker”)执行一个无限循环任务在循环中通过mln_trace发送追踪数据。动态追踪通过配置文件开启trace_mode可以捕获并处理mln_trace发送的数据。步骤 1编写程序代码 (task_scheduler.c)#includestdio.h#includestdlib.h#includeunistd.h#includemln_core.h#includemln_log.h#includemln_thread.h#includemln_trace.h#includemln_event.h#includemln_string.h// 全局开关0 表示杀掉线程1 表示创建线程staticintsw0;// 线程名staticcharworker_name[]worker;// 工作线程的入口函数staticintworker_entrance(intargc,char*argv[]){mln_log(debug,Worker thread started!\n);intcount0;while(1){// 模拟工作发送追踪数据mln_trace(d,Worker is running, count: %d,count);usleep(500000);// 休眠 0.5 秒}return0;}// 定时器处理函数管理 worker 线程的生命周期staticvoidtimer_handler(mln_event_t*ev,void*data){mln_string_taliasmln_string(worker_name);if(!sw){// 如果 sw 为 0尝试杀掉 worker 线程if(mln_thread_kill(alias)0){mln_log(debug,Killed worker thread.\n);}else{mln_log(warn,Failed to kill worker thread (maybe not exist).\n);}}else{// 如果 sw 为 1创建 worker 线程char**argv(char**)calloc(2,sizeof(char*));if(argv!NULL){argv[0]worker_name;argv[1]NULL;if(mln_thread_create(ev,worker_name,THREAD_DEFAULT,worker_entrance,1,argv)0){mln_log(debug,Created worker thread.\n);}else{mln_log(error,Failed to create worker thread.\n);}free(argv);// 注意mln_thread_create 内部会拷贝参数此处可以释放}}// 切换开关状态sw!sw;// 重新设置定时器实现每秒周期性执行mln_event_timer_set(ev,1000,NULL,timer_handler);}// 主线程的初始化函数由 Melon 框架在主线程中调用staticvoidmain_thread(mln_event_t*ev){// 启动定时器1秒后首次触发 timer_handlermln_event_timer_set(ev,1000,NULL,timer_handler);}intmain(intargc,char*argv[]){structmln_core_attrcattr;cattr.argcargc;cattr.argvargv;cattr.global_initNULL;// 全局初始化回调本例不需要cattr.main_threadmain_thread;// 主线程初始化回调cattr.worker_processNULL;// 不使用多进程cattr.master_processNULL;// 不使用 master 进程// 初始化 Melon 核心库if(mln_core_init(cattr)0){fprintf(stderr,Melon core init failed.\n);return-1;}// mln_core_init 会阻塞直到程序退出return0;}步骤 2配置 Melon (/usr/local/melon/conf/melon.conf)修改配置文件以启用多线程框架和动态追踪功能。log_level debug; # 日志级别便于调试 #user root; daemon off; # 前台运行方便查看输出 core_file_size unlimited; worker_proc 1; # 多进程模式下才有效 framework multithread; # 启用多线程框架 log_path /usr/local/melon/logs/melon.log; # 开启动态追踪模式指定处理脚本此处仅为示例实际需编写脚本 # trace_mode /path/to/your/trace_script.ml; # 为简化演示本例中注释掉 trace_modemln_trace 将不会执行额外处理 # trace_mode off; # 线程执行配置本例采用动态创建故此处无需配置 thread_exec { # restart worker; # 若配置此项框架会自动管理线程生命周期 }步骤 3编译与运行# 编译gcc-otask_scheduler task_scheduler.c-I/usr/local/melon/include/-L/usr/local/melon/lib/-lmelon# 运行需要在配置文件的目录下执行或设置环境变量./task_scheduler运行效果程序启动后你将看到类似以下的输出PID 和时间戳会不同Start up main thread... Worker thread started!Created worker thread. Worker is running, count:0Worker is running, count:1Killed worker thread. Failed tokillworker thread(maybe not exist). Created worker thread. Worker thread started!...程序会每秒交替执行“创建线程”和“杀掉线程”的操作生动地演示了 Melon 多线程框架的动态管理能力。六、配置与调试Melon 的强大之处在于通过配置文件melon.conf来控制其行为。安装后它通常位于安装路径的conf/子目录下。关键配置项log_level: 日志级别 (none,report,debug,warn,error)。daemon: 是否以守护进程方式运行 (on/off)。framework: 启用哪种框架 (multiprocess,multithread,off)。worker_proc: 当启用多进程框架时指定工作进程的数量。proc_exec/thread_exec: 用于静态配置需要由主进程/线程管理监控的子进程或子线程。keepalive/restart: 当子进程/线程退出时主进程/线程会将其重启。default: 子进程/线程退出后不做任何处理。七、最佳实践与常见问题最佳实践按需引入只包含你需要的头文件如mln_array.h避免不必要的编译依赖。善用内存池在频繁分配释放小块内存的场景优先使用 Melon 的内存池以提高性能。理解框架如果使用多进程或多线程框架请务必理解main_thread、worker_process、global_init等回调函数的执行时机和上下文。查阅文档Melon 的官方文档网站doc.melonc.io提供了每个模块的详细说明和示例是开发时的首要参考。常见问题Q: 编译时找不到头文件或库A: 检查-I和-L参数是否指向了正确的 Melon 安装路径。默认安装路径为/usr/local/melon。Q: 运行时提示error while loading shared libraries: libmelon.soA: 动态库路径未被系统识别。可以临时设置环境变量export LD_LIBRARY_PATH/usr/local/melon/lib:$LD_LIBRARY_PATH或将其添加到/etc/ld.so.conf中并执行ldconfig。Q: 多进程/多线程框架相关功能如mln_framework_init无法使用A: 请确保在配置文件中正确设置了framework指令例如framework multiprocess;或framework multithread;。Q: Windows 下编译链接失败A: 请确保在git bash或mingw环境中操作并使用正确的库名-llibmelon和链接 Windows Socket 库-lWs2_32。