提问人:Danny Holstein 提问时间:5/2/2023 最后编辑:ProgmanDanny Holstein 更新时间:5/5/2023 访问量:85
LibXML2 在 Python/ctypes 中封装时无法释放内存
LibXML2 failing to free memory when encapsulated in Python/ctypes
问:
我的 Python 脚本是:
def xmlEncodeSpecialChars(doc: xmlDoc, input: str) -> str:
'''
Do a global encoding of a string, replacing the predefined entities this routine is reentrant, and result must be deallocated.
doc: the document containing the string
input: A string to convert to XML.
Returns: A newly allocated string with the substitution done.'''
libXML = LibXML2() # DSO/DLL
libXML.xmlEncodeSpecialChars.restype = ctypes.c_char_p
libXML.xmlEncodeSpecialChars.argtypes = ctypes.c_void_p, ctypes.c_char_p,
output: ctypes.c_char_p = libXML.xmlEncodeSpecialChars(doc, input.encode());
Err = xmlGetLastError()
if Err: raise LibErr(Err)
ans = output.decode()
# free memory
libXML.xmlMemFree.argtypes = ctypes.c_char_p, ;
libXML.xmlMemFree(output)
return ans
它正确地返回一个转义字符串,但 xmlMemFree() 在 Python 中生成一个,尽管对同一 DLL 的等效 C 调用工作得很好。Memory tag error
如何设置内存空闲操作?ctypes
---编辑---
最低可重现 (Linux) 设置为:
def xmlEncodeSpecialChars(doc: xmlDoc, input: str) -> str:
'''
Do a global encoding of a string, replacing the predefined entities this routine is reentrant, and result must be deallocated.
doc: the document containing the string
input: A string to convert to XML.
Returns: A newly allocated string with the substitution done.'''
libXML = ctypes.CDLL ("libxml2.so.2") # DSO/DLL
libXML.xmlEncodeSpecialChars.restype = ctypes.c_void_p
libXML.xmlEncodeSpecialChars.argtypes = ctypes.c_void_p, ctypes.c_char_p,
output: ctypes.c_void_p = libXML.xmlEncodeSpecialChars(doc, input.encode());
Err = xmlGetLastError() # check for library error
if Err: raise LibErr(Err)
ans = ctypes.cast(output, ctypes.c_char_p).value.decode() # convert to Python str
libXML.xmlMemFree.argtypes = ctypes.c_void_p, ;libXML.xmlMemFree(output); # free memory, FIXME
return ans
print(xmlEncodeSpecialChars(None, "<root>Some text with < and > characters</root>"))
答:
0赞
Mark Tolonen
5/3/2023
#1
在 中,转换以 null 结尾的 C 并返回一个 Python 对象。指针丢失。ctypes
c_char_p
char*
bytes
使用或维护指针。 可用于读取返回地址处以 null 结尾的字符串。c_void_p
POINTER(c_char)
string_at
未经测试:
def xmlEncodeSpecialChars(doc: xmlDoc, input: str) -> str:
'''
Do a global encoding of a string, replacing the predefined entities this routine is reentrant, and result must be deallocated.
doc: the document containing the string
input: A string to convert to XML.
Returns: A newly allocated string with the substitution done.'''
libXML = LibXML2() # DSO/DLL
libXML.xmlEncodeSpecialChars.restype = ctypes.c_void_p
libXML.xmlEncodeSpecialChars.argtypes = ctypes.c_void_p, ctypes.c_char_p
output: ctypes.c_void_p = libXML.xmlEncodeSpecialChars(doc, input.encode())
Err = xmlGetLastError()
if Err: raise LibErr(Err)
ans = ctypes.string_at(output).decode()
# free memory
libXML.xmlMemFree.argtypes = ctypes.c_void_p,
libXML.xmlMemFree.restype = None
libXML.xmlMemFree(output)
return ans
评论
0赞
Danny Holstein
5/3/2023
我已经尝试过,并确信它会起作用。Memory tag error occurs :0x55580b699828 bye xmlMemFree(0x55580b699850) error xmlMallocBreakpoint reached on block 0
0赞
Danny Holstein
5/3/2023
我很高兴知道指针的转换和丢失。看来我还是丢了指针 😢c_char_p
0赞
Mark Tolonen
5/3/2023
@DannyHolstein 如果这不起作用,您还有其他问题。制作一个最小的可重现示例,并提供指向所用 DLL 的链接。我找不到任何文档链接。它也可以帮助了解它在 C 代码中的使用方式。使用 ?xmlEncodeSpecialChars
string_at
0赞
Danny Holstein
5/3/2023
我确定!只是为了咯咯笑,我把指针传递给了它,它工作得很好!xmlStrlen()
评论
c_void_p
c_char_p
c_char_p
# 4.4