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

请求协助设计带多类型void*参数的initialize函数的SWIG Python接口

解决方案

核心思路

通过SWIG的**类型映射(Type Maps)**结合Python层封装,将底层void*参数与具体的request1/request2、response1/response2结构体绑定,自动推导类型匹配关系,同时用Python包装函数隐藏底层的type参数和结构体细节,满足所有约束条件。

具体实现步骤

1. 声明C结构体与函数

在SWIG接口文件中引入C侧的结构体和函数定义:

%module example

// 引入C结构体声明
typedef struct {
    int param1;
} request1;

typedef struct {
    int result1;
} response1;

typedef struct {
    char* param2;
} request2;

typedef struct {
    char* result2;
} response2;

// 引入C函数声明
int initialize(int type, void *request, void *response);

2. 为结构体添加Python友好构造器

用%extend给结构体添加Python可直接调用的构造器,方便用户创建请求/响应对象(内存由Python侧管理,符合C不创建内存的约束):

%extend request1 {
    request1(int param1) {
        request1 *req = (request1*)malloc(sizeof(request1));
        req->param1 = param1;
        return req;
    }
}

%extend request2 {
    request2(const char* param2) {
        request2 *req = (request2*)malloc(sizeof(request2));
        req->param2 = strdup(param2);
        return req;
    }
}

%extend response1 {
    response1() {
        return (response1*)malloc(sizeof(response1));
    }
}

%extend response2 {
    response2() {
        return (response2*)malloc(sizeof(response2));
    }
}

3. 编写类型映射处理void*转换

通过类型映射自动识别Python对象对应的C结构体类型,转换为void*并传递正确的type值:

// 处理request参数:识别结构体类型,暂存type信息
%typemap(in) void *request (int type_val) {
    if (SWIG_ConvertPtr($input, (void**)&$1, $descriptor(request1*), 0) == SWIG_OK) {
        type_val = 1;
    } else if (SWIG_ConvertPtr($input, (void**)&$1, $descriptor(request2*), 0) == SWIG_OK) {
        type_val = 2;
    } else {
        SWIG_exception(SWIG_TypeError, "必须传入request1或request2对象");
    }
    // 将type值暂存到SWIG模块的客户端数据中
    swig_module->clientdata = (void*)(intptr_t)type_val;
}

// 处理response参数:根据暂存的type匹配对应的响应结构体
%typemap(in) void *response {
    int type = (int)(intptr_t)swig_module->clientdata;
    if (type == 1) {
        if (SWIG_ConvertPtr($input, (void**)&$1, $descriptor(response1*), 0) != SWIG_OK) {
            SWIG_exception(SWIG_TypeError, "type=1时必须传入response1对象");
        }
    } else if (type == 2) {
        if (SWIG_ConvertPtr($input, (void**)&$1, $descriptor(response2*), 0) != SWIG_OK) {
            SWIG_exception(SWIG_TypeError, "type=2时必须传入response2对象");
        }
    } else {
        SWIG_exception(SWIG_TypeError, "无效的请求类型");
    }
}

4. Python层封装统一调用接口

用%pythoncode添加包装函数,让用户无需关心底层的type参数:

%pythoncode %{
def initialize(request, response):
    # 调用底层C函数,类型映射已自动处理好void*和type匹配
    return _example.initialize(0, request, response)
%}

5. 用户使用示例

Python端调用完全无需感知底层细节:

import example

# 使用第一组结构体
req1 = example.request1(123)
resp1 = example.response1()
example.initialize(req1, resp1)
print(resp1.result1)

# 使用第二组结构体
req2 = example.request2("test_data")
resp2 = example.response2()
example.initialize(req2, resp2)
print(resp2.result2)

关键说明

  • 类型映射通过SWIG_ConvertPtr识别Python对象对应的C结构体,自动完成void*转换和类型匹配
  • 用swig_module->clientdata临时传递类型信息,确保request与response的类型一致性
  • 所有内存由Python侧(或用户)分配管理,符合C不创建内存的约束
  • 完全无需修改C代码,仅通过SWIG接口实现封装

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 13:03:37