如何将cmrc嵌入的脚本提供给要求物理文件的C++库?
解决方案
1. 类Unix系统:内存文件描述符(memfd_create)
利用系统提供的匿名内存文件机制,无需生成磁盘文件,直接通过/proc路径让lib2访问内存中的脚本内容。
示例代码:
#include <sys/memfd.h> #include <unistd.h> #include <fcntl.h> #include <string> #include <iterator> void pass_to_lib2(cmrc::file script) { // 创建匿名内存文件,带CLOEXEC标记避免泄露 int fd = memfd_create("embedded_script", MFD_CLOEXEC); if (fd == -1) { // 此处添加错误处理逻辑 return; } // 将lib1的脚本内容写入内存文件 std::string content(script.begin(), script.end()); write(fd, content.data(), content.size()); lseek(fd, 0, SEEK_SET); // 重置文件指针到起始位置 // 构造proc文件系统路径,传递给lib2 std::string fd_path = "/proc/self/fd/" + std::to_string(fd); lib2::file(fd_path.c_str()); close(fd); // 关闭后路径自动失效 }
2. Windows平台:命名管道
通过创建命名管道,将嵌入脚本写入管道,lib2通过管道路径读取内容,全程内存操作。
示例代码:
#include <windows.h> #include <string> #include <thread> // 子线程负责向管道写入内容 void pipe_writer(HANDLE pipe, const std::string& content) { DWORD bytes_written; WriteFile(pipe, content.data(), content.size(), &bytes_written, nullptr); CloseHandle(pipe); } void pass_to_lib2(cmrc::file script) { const char* pipe_name = "\\\\.\\pipe\\EmbeddedScriptPipe"; // 创建命名管道 HANDLE pipe = CreateNamedPipe( pipe_name, PIPE_ACCESS_OUTBOUND, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 0, 0, 0, nullptr ); if (pipe == INVALID_HANDLE_VALUE) { // 此处添加错误处理逻辑 return; } // 启动写入线程(lib2打开管道时会阻塞等待连接) std::string content(script.begin(), script.end()); std::thread writer(pipe_writer, pipe, content); writer.detach(); // 传递管道路径给lib2 lib2::file(pipe_name); }
3. Linux动态链接场景:LD_PRELOAD Hook
如果lib2是动态链接库,可以Hook它的文件操作函数,拦截指定路径请求,直接返回内存中的脚本内容。
Hook共享库代码(hook_fopen.c):
#define _GNU_SOURCE #include <stdio.h> #include <dlfcn.h> #include <string.h> // 约定的特殊路径标记 static const char* EMBED_MARKER = "::EMBEDDED_SCRIPT::"; // 全局变量存储脚本内容(主程序中赋值) extern const char* embed_content; extern size_t embed_size; FILE* fopen(const char* path, const char* mode) { static FILE* (*orig_fopen)(const char*, const char*) = NULL; if (!orig_fopen) { orig_fopen = dlsym(RTLD_NEXT, "fopen"); } if (strcmp(path, EMBED_MARKER) == 0) { // 将内存内容转为文件流返回 return fmemopen((void*)embed_content, embed_size, mode); } return orig_fopen(path, mode); }
主程序代码:
#include <dlfcn.h> #include <string> // 全局变量供Hook库访问 const char* embed_content; size_t embed_size; void pass_to_lib2(cmrc::file script) { embed_content = &(*script.begin()); embed_size = script.size(); // 加载Hook库 void* hook_lib = dlopen("./libhook_fopen.so", RTLD_LAZY); if (!hook_lib) { // 此处添加错误处理逻辑 return; } // 传递约定的标记路径给lib2 lib2::file("::EMBEDDED_SCRIPT::"); dlclose(hook_lib); }
编译Hook库:gcc -shared -fPIC -o libhook_fopen.so hook_fopen.c -ldl
方案选型建议
- 内存文件描述符:类Unix平台首选,实现简单无额外依赖,性能最优。
- 命名管道:Windows平台专属,需处理线程同步逻辑,适合Windows环境。
- LD_PRELOAD Hook:灵活性强,但需编写额外共享库,仅适用于Linux动态链接场景。
内容的提问来源于stack exchange,提问作者ad1v7
相关产品推荐
相关产品推荐

