我在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
内部构件,这是一个黑匣子。我只需要知道存储在calc()
中的my_result
结果。
是否可以通过某种方式简化ctypes
的{{1}}实施?我是否必须指定所有结构成员,包括子结构?或者我可以以某种方式传递足够的内存而无需指定所有结构细节?
答案 0 :(得分:0)
列出[Python 3.Docs]: ctypes - A foreign function library for Python。
如果您不关心结构的定义,并且由于两个函数都将指针作为参数,那么( Python )您唯一需要做的就是拥有足够大的缓冲区来容纳它(您可以使用 void 指针来引用 struct 实例)。
请记住,如果结构(递归)包含指向其他结构的指针,则也需要对这些结构进行分配(但我想这必须在 init中发生)。
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\StackOverflow\q058233135]> sopr.bat *** Set shorter prompt to better fit when pasted in StackOverflow (or other) pages *** [prompt]> "c:\Install\x86\Microsoft\Visual Studio Community\2017\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.