能否将SwigObject向下转型为具体类型?扩展Python端PtrRec识别
问题解答
结论:两种方案都可行,但修改C代码是更优选择
不需要强制修改C代码就能实现需求,但修改代码的方案更简洁、可维护;不修改代码的方案需要借助SWIG的包装技巧,相对繁琐。
方案一:不修改现有C代码,通过SWIG包装实现
利用SWIG的扩展机制和手动类型标记来区分两种实例:
- 在SWIG接口文件中,对
create_left和create_right的返回值进行包装,给每个返回的Ptr实例附加一个自定义类型标记(比如Python属性_type,值为"left"或"right") - 通过
%extend为Ptr类型添加get_size方法,在方法内部根据实例的类型标记,调用对应C侧的内部大小获取函数(需要确保left.c和right.c能提供对应的接口,比如get_left_size(Ptr)和get_right_size(Ptr)) - 示例SWIG代码片段:
%include "mid.h" // 给create_left的返回值打标记 %pythoncode %{ original_create_left = create_left def create_left(): ptr = original_create_left() ptr._type = "left" return ptr %} // 同理处理create_right %pythoncode %{ original_create_right = create_right def create_right(): ptr = original_create_right() ptr._type = "right" return ptr %} // 扩展get_size方法 %extend Ptr { int get_size() { PyObject *type_attr = PyObject_GetAttrString($self, "_type"); if (strcmp(PyUnicode_AsUTF8(type_attr), "left") == 0) { return get_left_size($self); } else if (strcmp(PyUnicode_AsUTF8(type_attr), "right") == 0) { return get_right_size($self); } PyErr_SetString(PyExc_TypeError, "Unknown Ptr type"); return -1; } } - 这种方式的缺点是依赖手动标记类型,没有编译期类型安全,容易出错,维护成本高。
方案二:修改C代码(推荐)
通过重命名结构并显式暴露类型,让SWIG直接识别不同的指针类型:
- 将left.c中的
struct PtrRec重命名为struct LeftPtrRec,right.c中的重命名为struct RightPtrRec - 在mid.h中显式声明两种指针类型:
typedef struct LeftPtrRec* LeftPtr; typedef struct RightPtrRec* RightPtr; - 修改left.c的
create_left返回LeftPtr,right.c的create_right返回RightPtr - 在SWIG接口文件中,分别为
LeftPtr和RightPtr添加%extend方法:%include "mid.h" %extend LeftPtr { int get_size() { return get_left_size($self); } } %extend RightPtr { int get_size() { return get_right_size($self); } } - 这种方式下,Python端会生成两个不同的类,直接通过类型判断就能区分实例,转型自然,类型安全,代码更清晰易维护。
内容的提问来源于stack exchange,提问作者Sugar
相关产品推荐
相关产品推荐

