我在获取指向工作结构的指针时遇到问题。这是我的代码,它抛出异常“ArgumentError:参数 1::预期 LP_LP_List 实例而不是指向 LP_LP_List 的指针”。
class List(Structure):
_fields_ = (
('head', POINTER(Node)),
('tail', POINTER(Node)),
('current', POINTER(Node)),
('saved', POINTER(Node)),
('infosize', c_int),
('listsize', c_ulong),
('current_index', c_ulong),
('save_index', c_ulong),
('modified', c_bool),
('search_origin', c_int),
('search_dir', c_int),
)
list_p = POINTER(List)
create = lib.DLL_CreateList
create.argtypes = [POINTER(POINTER(List)),]
create.restype = POINTER(List)
mem = POINTER(list_p)()
retval = create(byref(mem))
Run Code Online (Sandbox Code Playgroud)
这似乎遵循推荐的方法来执行此操作,但不起作用。
谢谢你的帮助。
对于那些不想阅读下面所有详细信息来查找解决方案的人,最后一部分应如下所示:
#list_p = POINTER(List) # Not needed
create = lib.DLL_CreateList
create.argtypes = [POINTER(POINTER(List)),]
create.restype = POINTER(List)
control = POINTER(List)()
list_p = create(byref(control))
Run Code Online (Sandbox Code Playgroud)
API听起来好像通过引用传入的指针会被create修改,所以它必须通过引用传递,返回值是新创建的列表。
如果这是用“C”编写的,我猜你会有这样的代码:
List *create(List **control);
List *control;
List *plist;
plist = create(&control);
Run Code Online (Sandbox Code Playgroud)
对于 ctypes/Python,这将映射到:
create.argtypes = [POINTER(POINTER(List)),]
create.restype = POINTER(List)
control = POINTER(List)()
newlist = create(byref(control))
Run Code Online (Sandbox Code Playgroud)
这样效果更好吗?
编辑:由于 create 都修改传入的参数并返回创建的列表,所以我会忘记返回并只保留参数:
create.argtypes = [POINTER(POINTER(List)),]
control = Pointer(List)()
create(byref(control))
Run Code Online (Sandbox Code Playgroud)
为了Python API的完整性,您可以考虑编写一个上下文管理器,来负责调用Create(当上下文管理器的__enter__方法被语句调用with以初始化列表控制块时),并自动调用Destroy(当上下文管理器的__exit__方法被初始化时)在语句范围的末尾调用with)。那么你的 Python 代码可能如下所示:
with listManager as ListManager():
# do stuff with list managed by list manager
# end of with statement, listManager.__exit__ is automatically called, so that Destroy always
# gets called, even if an exception is raised - this is easier for API users than expecting them
# to write their own try-finally code, and put Destroy in the finally block
Run Code Online (Sandbox Code Playgroud)
编辑:-我在 Ubuntu 上构建了你的 DLL 并使用了上面的 Python 代码,看来它毕竟创建了一个列表。
~/dev/python$ python
Python 2.6.6 (r266:84292, Sep 15 2010, 16:22:56)
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from ctypes import *
>>>
>>> class List(Structure): pass
...
>>> lib = CDLL('./libdll.so')
>>> create = lib.DLL_CreateList
>>> create.argtypes = [POINTER(POINTER(List)),]
>>> create.restype = POINTER(List)
>>>
>>> control = POINTER(List)()
>>> create(byref(control))
<__main__.LP_List object at 0x7fdc0c607e60>
Run Code Online (Sandbox Code Playgroud)
编辑 - 我编写了一个 pyparsing 实用程序来读取 C 头文件并输出占位符结构子类以及函数 argtypes 和 restype 定义。这是我为您的库提供的内容 - 它尚未经过测试,但可能会帮助您快速启动 API 测试:
from ctypes import *
ll = CDLL("./libdll.so")
# user defined types
class ll_Info(Structure): pass
class ll_DLL_Boolean(Structure): pass
class ll_DLL_SrchOrigin(Structure): pass
class sys_select_fd_set(Structure): pass
class ll_List(Structure): pass
class sys_time_timeval(Structure): pass
class ll_DLL_SrchDir(Structure): pass
class ll_DLL_Return(Structure): pass
class ll_DLL_SearchModes(Structure): pass
class ll_DLL_InsertDir(Structure): pass
# functions
ll.DLL_CreateList.restype = POINTER(ll_List)
ll.DLL_CreateList.argtypes = (POINTER(POINTER(ll_List)),)
ll.DLL_DestroyList.restype = None
ll.DLL_DestroyList.argtypes = (POINTER(POINTER(ll_List)),)
ll.DLL_Version.restype = c_char_p
ll.DLL_Version.argtypes = ()
ll.DLL_IsListEmpty.restype = ll_DLL_Boolean
ll.DLL_IsListEmpty.argtypes = (POINTER(ll_List),)
ll.DLL_IsListFull.restype = ll_DLL_Boolean
ll.DLL_IsListFull.argtypes = (POINTER(ll_List),)
ll.DLL_CurrentPointerToHead.restype = ll_DLL_Return
ll.DLL_CurrentPointerToHead.argtypes = (POINTER(ll_List),)
ll.DLL_CurrentPointerToTail.restype = ll_DLL_Return
ll.DLL_CurrentPointerToTail.argtypes = (POINTER(ll_List),)
ll.DLL_DecrementCurrentPointer.restype = ll_DLL_Return
ll.DLL_DecrementCurrentPointer.argtypes = (POINTER(ll_List),)
ll.DLL_DeleteCurrentRecord.restype = ll_DLL_Return
ll.DLL_DeleteCurrentRecord.argtypes = (POINTER(ll_List),)
ll.DLL_DeleteEntireList.restype = ll_DLL_Return
ll.DLL_DeleteEntireList.argtypes = (POINTER(ll_List),)
ll.DLL_FindNthRecord.restype = ll_DLL_Return
ll.DLL_FindNthRecord.argtypes = (POINTER(ll_List),POINTER(ll_Info),c_ulong,)
ll.DLL_GetCurrentRecord.restype = ll_DLL_Return
ll.DLL_GetCurrentRecord.argtypes = (POINTER(ll_List),POINTER(ll_Info),)
ll.DLL_GetNextRecord.restype = ll_DLL_Return
ll.DLL_GetNextRecord.argtypes = (POINTER(ll_List),POINTER(ll_Info),)
ll.DLL_GetPriorRecord.restype = ll_DLL_Return
ll.DLL_GetPriorRecord.argtypes = (POINTER(ll_List),POINTER(ll_Info),)
ll.DLL_InitializeList.restype = ll_DLL_Return
ll.DLL_InitializeList.argtypes = (POINTER(ll_List),c_size_t,)
ll.DLL_IncrementCurrentPointer.restype = ll_DLL_Return
ll.DLL_IncrementCurrentPointer.argtypes = (POINTER(ll_List),)
ll.DLL_InsertRecord.restype = ll_DLL_Return
ll.DLL_InsertRecord.argtypes = (POINTER(ll_List),POINTER(ll_Info),ll_DLL_InsertDir,)
ll.DLL_RestoreCurrentPointer.restype = ll_DLL_Return
ll.DLL_RestoreCurrentPointer.argtypes = (POINTER(ll_List),)
ll.DLL_SaveList.restype = ll_DLL_Return
ll.DLL_SaveList.argtypes = (POINTER(ll_List),c_char_p,)
ll.DLL_SetSearchModes.restype = ll_DLL_Return
ll.DLL_SetSearchModes.argtypes = (POINTER(ll_List),ll_DLL_SrchOrigin,ll_DLL_SrchDir,)
ll.DLL_StoreCurrentPointer.restype = ll_DLL_Return
ll.DLL_StoreCurrentPointer.argtypes = (POINTER(ll_List),)
ll.DLL_SwapRecord.restype = ll_DLL_Return
ll.DLL_SwapRecord.argtypes = (POINTER(ll_List),ll_DLL_InsertDir,)
ll.DLL_UpdateCurrentRecord.restype = ll_DLL_Return
ll.DLL_UpdateCurrentRecord.argtypes = (POINTER(ll_List),POINTER(ll_Info),)
ll.DLL_GetSearchModes.restype = POINTER(ll_DLL_SearchModes)
ll.DLL_GetSearchModes.argtypes = (POINTER(ll_List),POINTER(ll_DLL_SearchModes),)
ll.DLL_GetCurrentIndex.restype = c_ulong
ll.DLL_GetCurrentIndex.argtypes = (POINTER(ll_List),)
ll.DLL_GetNumberOfRecords.restype = c_ulong
ll.DLL_GetNumberOfRecords.argtypes = (POINTER(ll_List),)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9547 次 |
| 最近记录: |