我有一个共享 C 库,其中包含一个我想在 python 代码中使用的结构
struct my_struct {
char name[64];
};
所以在Python中我用
重新创建它class MyStruct(ctypes.Structure):
_fields_ = [
("name", ctypes.c_char*64)
]
当我检查 MyStruct.name 的类型时,我得到“str”,而我期望的是“c_char_Array_64”。
s=MyStruct()
print type(s.name) # <type 'str'>
因此,当我设置“名称”并尝试使用它时,C 将其视为空白。
s.name="Martin"
lib=ctypes.cdll.LoadLibrary('./mylib.so')
lib.my_func(s) # prints ''
其中 lib 是加载了 ctypes 的共享 C 库,而 my_func 只是打印 struct->name
void my_func(struct my_struct *s){
printf("Hello %s\n", s->name);
}
我想知道为什么 ctypes.Structure 将 char 数组转换为字符串以及如何在上面指定的情况下使用它。
谢谢你
Tnanks 向@CristiFati 寻求调试此问题的帮助。我已将他的答案标记为正确,因为它实际上是所发布问题的答案。就我而言,问题在于 Python 和 C 程序中的结构体不是“等长”的。因此,对于将来偶然发现这个问题的人,请非常仔细地检查您的结构是否实际上是平等定义的。
[Python.Docs]:ctypes - Python 的外部函数库
作为参考。
:
#include <stdio.h>
#include <stdlib.h>
#if defined(_WIN32)
# define DLL00_EXPORT __declspec(dllexport)
#else
# define DLL00_EXPORT
#endif
typedef struct Struct0_ {
char name[64];
} Struct0;
DLL00_EXPORT void test(Struct0 *ps0)
{
printf("Hello %s\n", ps0->name);
}
:
#!/usr/bin/env python
import ctypes as cts
import sys
DLL_NAME = "./dll00.{:s}".format("dll" if sys.platform[:3].lower() == "win" else "so")
CharArr64 = cts.c_char * 64
class Struct0(cts.Structure):
_fields_ = (
("name", CharArr64),
)
def main():
dll = cts.CDLL(DLL_NAME)
test = dll.test
test.argtypes = (cts.POINTER(Struct0),)
s0 = Struct0()
s0.name = b"Martin"
res = test(cts.pointer(s0))
if __name__ == "__main__":
print(
"Python {:s} {:03d}bit on {:s}\n".format(
" ".join(elem.strip() for elem in sys.version.split("\n")),
64 if sys.maxsize > 0x100000000 else 32,
sys.platform,
)
)
rc = main(*sys.argv[1:])
print("\nDone.\n")
sys.exit(rc)
:
(py_064_03.06.08_test0) e:\Work\Dev\StackOverflow\q054089371> "c:\Install\x86\Microsoft\Visual Studio Community\2015\vc\vcvarsall.bat" x64
(py_064_03.06.08_test0) e:\Work\Dev\StackOverflow\q054089371>dir /b
code00.py
dll00.c
(py_064_03.06.08_test0) e:\Work\Dev\StackOverflow\q054089371> cl /nologo /DDLL /MD dll00.c /link /NOLOGO /DLL /OUT:dll00.dll
dll00.c
Creating library dll00.lib and object dll00.exp
(py_064_03.06.08_test0) e:\Work\Dev\StackOverflow\q054089371> dir /b
code00.py
dll00.c
dll00.dll
dll00.exp
dll00.lib
dll00.obj
(py_064_03.06.08_test0) e:\Work\Dev\StackOverflow\q054089371>"e:\Work\Dev\VEnvs\py_064_03.06.08_test0\Scripts\python.exe" ./code00.py
Python 3.6.8 (tags/v3.6.8:3c6b436a57, Dec 24 2018, 00:16:47) [MSC v.1916 64 bit (AMD64)] on win32
Hello Martin
Done.
(py_064_03.06.08_test0) e:\Work\Dev\StackOverflow\q054089371> rem Also run with Python 2.7 ... Not recommended.
(py_064_03.06.08_test0) e:\Work\Dev\StackOverflow\q054089371> "e:\Work\Dev\VEnvs\py_064_02.07.15_test0\Scripts\python.exe" ./code00.py
Python 2.7.15 (v2.7.15:ca079a3ea3, Apr 30 2018, 16:30:26) [MSC v.1500 64 bit (AMD64)] on win32
Hello Martin
Done.
可能还想检查[SO]:通过ctypes从Python调用的C函数返回不正确的值(@CristiFati的答案)