共享库中字符数组为空的 ctypes 结构
ctypes structure with char array empty in shared library
我有一个共享的 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'>
所以当我设置 'name' 并尝试使用它时,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 将字符数组转换为字符串以及如何在上述情况下使用它。
谢谢
更新与解决方案
感谢@CristiFati 帮助调试此问题。我已将他的回答标记为正确,因为它实际上是对发布的问题的回答。在我的例子中,问题是 Python 和 C 程序中的结构不是 等长 。因此,对于将来偶然发现此问题的任何人,请非常仔细地检查您的结构实际上是否定义相同。
你做错了什么,但不看完整代码我不能说是什么。所以我准备了一个有用的小例子。
我也张贴 [Python 3]: ctypes - A foreign function library for Python 作为参考。
dll.c:
#include <stdio.h>
#include <stdlib.h>
#if defined(_WIN32)
# define DLL_EXPORT __declspec(dllexport)
#else
# define DLL_EXPORT
#endif
typedef struct Struct0_ {
char name[64];
} Struct0;
DLL_EXPORT void test(Struct0 *ps0){
printf("Hello %s\n", ps0->name);
}
code.py:
#!/usr/bin/env python3
import sys
import ctypes
DLL = "./dll.dll"
CharArr64 = ctypes.c_char * 64
class Struct0(ctypes.Structure):
_fields_ = [
("name", CharArr64),
]
def main():
dll_dll = ctypes.CDLL(DLL)
test_func = dll_dll.test
test_func.argtypes = [ctypes.POINTER(Struct0)]
s0 = Struct0()
s0.name = b"Martin"
res = test_func(ctypes.pointer(s0))
if __name__ == "__main__":
print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
main()
输出:
(py_064_03.06.08_test0) e:\Work\Dev\Whosebug\q054089371>"c:\Install\x86\Microsoft\Visual Studio Community15\vc\vcvarsall.bat" x64
(py_064_03.06.08_test0) e:\Work\Dev\Whosebug\q054089371>dir /b
code.py
dll.c
(py_064_03.06.08_test0) e:\Work\Dev\Whosebug\q054089371>cl /nologo /DDLL /MD dll.c /link /NOLOGO /DLL /OUT:dll.dll
dll.c
Creating library dll.lib and object dll.exp
(py_064_03.06.08_test0) e:\Work\Dev\Whosebug\q054089371>dir /b
code.py
dll.c
dll.dll
dll.exp
dll.lib
dll.obj
(py_064_03.06.08_test0) e:\Work\Dev\Whosebug\q054089371>"e:\Work\Dev\VEnvs\py_064_03.06.08_test0\Scripts\python.exe" code.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
(py_064_03.06.08_test0) e:\Work\Dev\Whosebug\q054089371>rem Also run with Python 2.7 ... Not recommended.
(py_064_03.06.08_test0) e:\Work\Dev\Whosebug\q054089371>"e:\Work\Dev\VEnvs\py_064_02.07.15_test0\Scripts\python.exe" code.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
我有一个共享的 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'>
所以当我设置 'name' 并尝试使用它时,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 将字符数组转换为字符串以及如何在上述情况下使用它。
谢谢
更新与解决方案
感谢@CristiFati 帮助调试此问题。我已将他的回答标记为正确,因为它实际上是对发布的问题的回答。在我的例子中,问题是 Python 和 C 程序中的结构不是 等长 。因此,对于将来偶然发现此问题的任何人,请非常仔细地检查您的结构实际上是否定义相同。
你做错了什么,但不看完整代码我不能说是什么。所以我准备了一个有用的小例子。
我也张贴 [Python 3]: ctypes - A foreign function library for Python 作为参考。
dll.c:
#include <stdio.h>
#include <stdlib.h>
#if defined(_WIN32)
# define DLL_EXPORT __declspec(dllexport)
#else
# define DLL_EXPORT
#endif
typedef struct Struct0_ {
char name[64];
} Struct0;
DLL_EXPORT void test(Struct0 *ps0){
printf("Hello %s\n", ps0->name);
}
code.py:
#!/usr/bin/env python3
import sys
import ctypes
DLL = "./dll.dll"
CharArr64 = ctypes.c_char * 64
class Struct0(ctypes.Structure):
_fields_ = [
("name", CharArr64),
]
def main():
dll_dll = ctypes.CDLL(DLL)
test_func = dll_dll.test
test_func.argtypes = [ctypes.POINTER(Struct0)]
s0 = Struct0()
s0.name = b"Martin"
res = test_func(ctypes.pointer(s0))
if __name__ == "__main__":
print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
main()
输出:
(py_064_03.06.08_test0) e:\Work\Dev\Whosebug\q054089371>"c:\Install\x86\Microsoft\Visual Studio Community15\vc\vcvarsall.bat" x64 (py_064_03.06.08_test0) e:\Work\Dev\Whosebug\q054089371>dir /b code.py dll.c (py_064_03.06.08_test0) e:\Work\Dev\Whosebug\q054089371>cl /nologo /DDLL /MD dll.c /link /NOLOGO /DLL /OUT:dll.dll dll.c Creating library dll.lib and object dll.exp (py_064_03.06.08_test0) e:\Work\Dev\Whosebug\q054089371>dir /b code.py dll.c dll.dll dll.exp dll.lib dll.obj (py_064_03.06.08_test0) e:\Work\Dev\Whosebug\q054089371>"e:\Work\Dev\VEnvs\py_064_03.06.08_test0\Scripts\python.exe" code.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 (py_064_03.06.08_test0) e:\Work\Dev\Whosebug\q054089371>rem Also run with Python 2.7 ... Not recommended. (py_064_03.06.08_test0) e:\Work\Dev\Whosebug\q054089371>"e:\Work\Dev\VEnvs\py_064_02.07.15_test0\Scripts\python.exe" code.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