ctypes:如何处理包含结构的结构,其中包含结构......?
ctypes: How to hande structure which contains structure which contains structure which...?
我在 C:
中有一个简单的 API
void init( t_main_struct* p_main_struct );
void calc( t_main_struct* p_main_struct, float* p_result );
我用作:
t_main_struct my_main_struct;
float my_result[3];
init(&my_main_struct);
calc(&my_main_struct, my_result);
我想使用 Python ctypes
.
包装上面的 API
问题是,t_main_struct
非常复杂:包含其他结构,包含其他结构,包含其他结构,等等。
在 Python 方面,我真的不需要访问任何 my_main_struct
内部结构,它是一个黑盒子。我只需要知道 my_result
中存储的 calc()
结果。
是否有可能以某种方式简化 main_struct
的 ctypes
实施?我是否必须指定所有结构成员,包括子结构?或者我可以在不指定所有结构细节的情况下以某种方式传递足够的内存?
清单[Python 3.Docs]: ctypes - A foreign function library for Python.
如果您不关心结构的定义,并且由于两个函数都将指针作为参数,(在 Python 中)您唯一需要做的, 有一个足够大的缓冲区来容纳它(你可以使用 void 指针来引用 struct 实例)。
请记住,如果结构(递归地)包含指向其他结构的指针,则也需要分配这些指针 如果被引用(但我想这必须发生在初始化).
dll00.c:
#if defined(_WIN32)
# define DLL00_EXPORT_API __declspec(dllexport)
#else
# define DLL00_EXPORT_API
#endif
typedef struct _ComplexStruct {
float f0;
int i0;
// The other members
} ComplexStruct;
#if defined(__cplusplus)
extern "C" {
#endif
DLL00_EXPORT_API void init(ComplexStruct *pStruct);
DLL00_EXPORT_API void calc(ComplexStruct *pStruct, float *pResult);
#if defined(__cplusplus)
}
#endif
DLL00_EXPORT_API void init(ComplexStruct *pStruct) {
if (pStruct) {
pStruct->f0 = -3.5;
pStruct->i0 = 5;
}
}
DLL00_EXPORT_API void calc(ComplexStruct *pStruct, float *pResult) {
if ((pStruct) && (pResult)) {
(*pResult) = pStruct->f0 * pStruct->i0;
}
}
code00.py:
#!/usr/bin/env python3
import sys
import ctypes
DLL_NAME = "./dll00.dll"
def main():
dll00 = ctypes.CDLL(DLL_NAME)
init = dll00.init
init.argtypes = [ctypes.c_void_p]
init.restype = None
calc = dll00.calc
calc.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_float)]
calc.restype = None
buf = ctypes.create_string_buffer(512) # Create a buffer large enough to hold the structure
init(buf)
res = ctypes.c_float()
calc(buf, ctypes.byref(res))
print("Result: {0:.3f}".format(res.value))
if __name__ == "__main__":
print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(item.strip() for item in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))
main()
print("\nDone.")
输出:
[cfati@CFATI-5510-0:e:\Work\Dev\Whosebug\q058233135]> sopr.bat
*** Set shorter prompt to better fit when pasted in Whosebug (or other) pages ***
[prompt]> "c:\Install\x86\Microsoft\Visual Studio Community17\VC\Auxiliary\Build\vcvarsall.bat" x64
**********************************************************************
** Visual Studio 2017 Developer Command Prompt v15.9.16
** Copyright (c) 2017 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64'
[prompt]> dir /b
code00.py
dll00.c
[prompt]> cl /nologo /DDLL dll00.c /link /NOLOGO /DLL /OUT:dll00.dll
dll00.c
Creating library dll00.lib and object dll00.exp
[prompt]> dir /b
code00.py
dll00.c
dll00.dll
dll00.exp
dll00.lib
dll00.obj
[prompt]> "e:\Work\Dev\VEnvs\py_064_03.07.03_test0\Scripts\python.exe" code00.py
Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] 64bit on win32
Result: -17.500
Done.
我在 C:
中有一个简单的 APIvoid init( t_main_struct* p_main_struct );
void calc( t_main_struct* p_main_struct, float* p_result );
我用作:
t_main_struct my_main_struct;
float my_result[3];
init(&my_main_struct);
calc(&my_main_struct, my_result);
我想使用 Python ctypes
.
问题是,t_main_struct
非常复杂:包含其他结构,包含其他结构,包含其他结构,等等。
在 Python 方面,我真的不需要访问任何 my_main_struct
内部结构,它是一个黑盒子。我只需要知道 my_result
中存储的 calc()
结果。
是否有可能以某种方式简化 main_struct
的 ctypes
实施?我是否必须指定所有结构成员,包括子结构?或者我可以在不指定所有结构细节的情况下以某种方式传递足够的内存?
清单[Python 3.Docs]: ctypes - A foreign function library for Python.
如果您不关心结构的定义,并且由于两个函数都将指针作为参数,(在 Python 中)您唯一需要做的, 有一个足够大的缓冲区来容纳它(你可以使用 void 指针来引用 struct 实例)。
请记住,如果结构(递归地)包含指向其他结构的指针,则也需要分配这些指针 如果被引用(但我想这必须发生在初始化).
dll00.c:
#if defined(_WIN32)
# define DLL00_EXPORT_API __declspec(dllexport)
#else
# define DLL00_EXPORT_API
#endif
typedef struct _ComplexStruct {
float f0;
int i0;
// The other members
} ComplexStruct;
#if defined(__cplusplus)
extern "C" {
#endif
DLL00_EXPORT_API void init(ComplexStruct *pStruct);
DLL00_EXPORT_API void calc(ComplexStruct *pStruct, float *pResult);
#if defined(__cplusplus)
}
#endif
DLL00_EXPORT_API void init(ComplexStruct *pStruct) {
if (pStruct) {
pStruct->f0 = -3.5;
pStruct->i0 = 5;
}
}
DLL00_EXPORT_API void calc(ComplexStruct *pStruct, float *pResult) {
if ((pStruct) && (pResult)) {
(*pResult) = pStruct->f0 * pStruct->i0;
}
}
code00.py:
#!/usr/bin/env python3
import sys
import ctypes
DLL_NAME = "./dll00.dll"
def main():
dll00 = ctypes.CDLL(DLL_NAME)
init = dll00.init
init.argtypes = [ctypes.c_void_p]
init.restype = None
calc = dll00.calc
calc.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_float)]
calc.restype = None
buf = ctypes.create_string_buffer(512) # Create a buffer large enough to hold the structure
init(buf)
res = ctypes.c_float()
calc(buf, ctypes.byref(res))
print("Result: {0:.3f}".format(res.value))
if __name__ == "__main__":
print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(item.strip() for item in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))
main()
print("\nDone.")
输出:
[cfati@CFATI-5510-0:e:\Work\Dev\Whosebug\q058233135]> sopr.bat *** Set shorter prompt to better fit when pasted in Whosebug (or other) pages *** [prompt]> "c:\Install\x86\Microsoft\Visual Studio Community17\VC\Auxiliary\Build\vcvarsall.bat" x64 ********************************************************************** ** Visual Studio 2017 Developer Command Prompt v15.9.16 ** Copyright (c) 2017 Microsoft Corporation ********************************************************************** [vcvarsall.bat] Environment initialized for: 'x64' [prompt]> dir /b code00.py dll00.c [prompt]> cl /nologo /DDLL dll00.c /link /NOLOGO /DLL /OUT:dll00.dll dll00.c Creating library dll00.lib and object dll00.exp [prompt]> dir /b code00.py dll00.c dll00.dll dll00.exp dll00.lib dll00.obj [prompt]> "e:\Work\Dev\VEnvs\py_064_03.07.03_test0\Scripts\python.exe" code00.py Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] 64bit on win32 Result: -17.500 Done.