如何用Python的ctypes修改对象地址指向的参数值?
问题:通过ctypes修改Python对象的属性值
我正在为学校作业编写链表程序,遇到了技术问题:使用ctypes库时,已知某个对象的地址,如何修改该对象中存储地址的参数值?例如,要在链表末尾添加节点,已知尾节点(对象)的地址,需将其next属性从None改为新节点的地址。
我尝试了以下代码但未生效,以为是仅修改了对象引用而非地址中的实际值:
this_Node = ctypes.cast(this_pointer, ctypes.py_object).value this_Node.next = new_node_adress
以下是完整代码:
import ctypes class Node: def __init__(self,data,next): self.data = data self.next = next #initialise linked list LinkedList = [] for i in range(0,10): LinkedList.append(Node(i,None)) for i in range(0,9): LinkedList[i].next = id(LinkedList[i+1]) root_pointer= id(LinkedList[0]) #print(ctypes.cast(root_pointer, ctypes.py_object).value.data) #search in linked list def search_value(root_pointer,f): found = False this_address = root_pointer this_Node = ctypes.cast(root_pointer, ctypes.py_object).value this_pointer = this_Node.next while this_Node.next != None and found == False: #print(this_Node.data) if f == this_Node.data: found = True print(f,"was found in address",this_address) else: this_address = this_Node.next this_Node = ctypes.cast(this_pointer, ctypes.py_object).value this_pointer = this_Node.next if found ==False: print(f,"was not in the list") return found, this_address,this_Node,this_pointer def end_add(root_pointer,new_node_adress): this_address = root_pointer this_Node = ctypes.cast(root_pointer, ctypes.py_object).value this_pointer = this_Node.next while this_Node.next != None: this_address = this_Node.next this_Node = ctypes.cast(this_pointer, ctypes.py_object).value this_pointer = this_Node.next this_Node.next = new_node_adress f = 34 a = Node(34,None) end_add(root_pointer,id(a)) #print(ctypes.cast(root_pointer, ctypes.py_object).value.data) found,this_address,this_Node,this_pointer=search_value(root_pointer,f)
解决方案
首先明确:你对ctypes.cast的使用是正确的,ctypes.cast(this_pointer, ctypes.py_object).value确实能获取对应地址的原Python对象,修改它的属性就是直接修改原对象的属性,不存在“只修改引用”的问题。代码未生效的根本原因是**search_value的遍历逻辑遗漏了最后一个节点**。
问题分析
你的Node类的next属性存储的是对象的id(整数类型地址),end_add函数已经正确将尾节点的next设置为新节点的id,但search_value的循环条件this_Node.next != None会在遍历到尾节点时直接退出,导致没有检查尾节点的data值,所以找不到新添加的节点。
修正步骤
- 调整
search_value的遍历逻辑,先检查当前节点的data,再判断是否需要继续遍历下一个节点,确保覆盖所有节点。 - 简化
end_add的遍历代码,去掉冗余的变量。
修正后的完整代码
import ctypes class Node: def __init__(self,data,next): self.data = data self.next = next # 初始化链表 LinkedList = [] for i in range(0,10): LinkedList.append(Node(i,None)) for i in range(0,9): LinkedList[i].next = id(LinkedList[i+1]) root_pointer= id(LinkedList[0]) # 链表查找函数 def search_value(root_pointer,f): found = False this_address = root_pointer this_Node = ctypes.cast(root_pointer, ctypes.py_object).value while True: # 先检查当前节点的数据 if f == this_Node.data: found = True print(f,"was found in address",this_address) break # 没有下一个节点则退出循环 if this_Node.next is None: break # 移动到下一个节点 this_address = this_Node.next this_Node = ctypes.cast(this_address, ctypes.py_object).value if not found: print(f,"was not in the list") return found, this_address,this_Node # 链表末尾添加节点函数 def end_add(root_pointer,new_node_adress): this_Node = ctypes.cast(root_pointer, ctypes.py_object).value # 遍历找到尾节点 while this_Node.next != None: this_Node = ctypes.cast(this_Node.next, ctypes.py_object).value # 修改尾节点的next属性 this_Node.next = new_node_adress # 测试代码 f = 34 a = Node(34,None) end_add(root_pointer,id(a)) found,this_address,this_Node = search_value(root_pointer,f)
关键说明
- 修改对象属性的操作是有效的:
this_Node = ctypes.cast(...)拿到的是原对象的引用,修改this_Node.next会直接改变原节点的属性值。 - 遍历逻辑的调整是核心:确保每个节点的
data都被检查到,包括最后一个节点。
内容的提问来源于stack exchange,提问作者Alejandro Sanchez
相关产品推荐
相关产品推荐

