You need to enable JavaScript to run this app. C++如何向从DLL读取的未知签名函数传递任意数量JSON参数
优惠活动
大模型
产品
解决方案
定价
更多

C++如何向从DLL读取的未知签名函数传递任意数量JSON参数

C++ 动态调用DLL原生函数的参数传递解决方案

疑问解答:是否可以用单个vector代替多个参数传入原生函数?

完全不可行。C/C++原生函数的参数传递遵循固定的调用约定,要求参数按照指定顺序、内存布局压栈或者存入对应寄存器,vector是容器对象,内存布局和原生参数序列完全不匹配,且你无法修改目标函数实现的前提下,该思路完全不适用。

最优通用解决方案:使用libffi

libffi是专门用于运行时动态构造原生函数调用的底层工具库,不需要你预先知道目标函数的参数个数、类型,完全适配你从JSON读取参数、从DLL动态获取函数地址的场景,可彻底替换你现在手写固定参数个数if分支的临时方案。

核心实现步骤

  • 从DLL中读取目标函数的地址,保存为void*类型的函数指针
  • 遍历解析后的JSON参数,逐个匹配每个参数的类型,填充参数类型数组、参数值指针数组
  • 初始化libffi的调用上下文ffi_cif,指定调用约定、参数个数、返回值类型、参数类型数组
  • 调用ffi_call接口,传入上下文、函数指针、返回值存储地址、参数值指针数组,即可完成任意参数个数的函数调用

简化代码示例

#include <ffi.h>
#include <vector>
// 以下为示例逻辑,你可以根据自己的JSON解析逻辑适配
void* func = GetProcAddress(loaded_dll_handle, target_func_name.c_str());
int param_cnt = parsed_json_param_array.size();

std::vector<ffi_type*> arg_types(param_cnt);
std::vector<void*> arg_values(param_cnt);

// 遍历填充参数类型和值
for (int i = 0; i < param_cnt; ++i) {
    const auto& json_param = parsed_json_param_array[i];
    if (json_param.is_integer()) {
        arg_types[i] = &ffi_type_sint32;
        static int val = json_param.as_integer();
        arg_values[i] = &val;
    } else if (json_param.is_string()) {
        arg_types[i] = &ffi_type_pointer;
        static const char* val = json_param.as_string().c_str();
        arg_values[i] = &val;
    }
    // 其他类型(浮点、指针、结构体等)可自行扩展匹配
}

// 初始化调用上下文,此处默认使用cdecl调用约定,返回值为int类型
ffi_cif cif;
ffi_status init_ret = ffi_prep_cif(&cif, FFI_DEFAULT_ABI, param_cnt, &ffi_type_sint32, arg_types.data());
if (init_ret == FFI_OK) {
    int func_return_val;
    ffi_call(&cif, FFI_FN(func), &func_return_val, arg_values.data());
    // func_return_val即为目标函数的返回结果
}

轻量替代方案(无第三方库依赖)

如果你的场景中允许限定最大参数个数,且不想引入libffi依赖,可以用C++11及以上版本的可变参数模板+编译期索引展开,自动生成不同参数个数的调用分支,不需要手动写if判断,代码可维护性远高于你现在的临时实现。

内容的提问来源于stack exchange,提问作者David

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.11 13:45:02