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

如何将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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 21:30:49