我无法从python中访问 c类型 的 绳子 由C代码(dll库)分配的引用结构。但是 昵 我可以访问和更改的类型。
这是简化后的代码,实际上我访问的是我无法改变的专有dll,因此请把这个dll的内容当作固定的。实际上我访问的是专有的dll,我无法改变,所以请把这个dll的内容当作固定的内容,我能够从C代码中访问dll结构字符串,没有问题--这是我构造这个例子dll的方式,所以它的接口和专有dll的接口是一样的。
我的假设是,错误的是要么python声明的 "文本" 在 DATA_STRUCT (各种测试过的可能性都列出来了),或者我想访问字符串的方式--都被注释了,因为它们要么只返回对象,要么在windows下失败(访问违规)。
需要说明的是,我使用的是Dev-C++提供的编译器TDM-GCC 4.9.2 64位(应该使用MingW64)和64位Python 3.8.2.使用64位Python的原因是专有的dll,是64位的。
dll.h
typedef struct REFERENCE_STRUCT {
int type ;
void * dataP ;
} REFERENCE_STRUCT ;
typedef struct DATA_STRUCT {
int number ;
char text [41] ; // the string is fixed length
} DATA_STRUCT ;
__declspec(dllexport) int test_alloc (REFERENCE_STRUCT *refP) ;
__declspec(dllexport) int test_print (REFERENCE_STRUCT *refP) ;
__declspec(dllexport) int test_free (REFERENCE_STRUCT *refP) ;
maindll.c
#include "dll.h"
#include <windows.h>
#include <string.h>
#include <stdio.h>
__declspec(dllexport) int test_alloc (REFERENCE_STRUCT *refP) {
DATA_STRUCT *dataP ;
dataP = malloc (sizeof (DATA_STRUCT));
dataP->number = 5 ;
strcpy (dataP->text, "number 1");
refP->type = 40 ;
refP->dataP = ( void *) dataP ;
printf ("DLL - alloc: reference type: %d; data <%d>; <%s>\n", refP->type, dataP->number, dataP->text) ;
return 0;
} ;
__declspec(dllexport) int test_print (REFERENCE_STRUCT *refP) {
DATA_STRUCT *dataP ;
dataP = (DATA_STRUCT*) refP->dataP ;
printf ("DLL - print: reference type: %d; data <%d>; <%s>\n", refP->type, dataP->number, dataP->text) ;
return 0;
} ;
__declspec(dllexport) int test_free (REFERENCE_STRUCT *refP){
free(refP->dataP) ;
printf ("DLL - free\n") ;
return 0;
} ;
脚本.py
import sys,os, ctypes, ctypes.util, faulthandler
faulthandler.enable()
os.add_dll_directory("D:/path_to_lib/")
mylib_path = ctypes.util.find_library("mydll")
mylib = ctypes.CDLL(mylib_path)
class REFERENCE_STRUCT(ctypes.Structure):
_fields_ = [("type", ctypes.c_int),
("dataP", ctypes.c_void_p)]
class DATA_STRUCT(ctypes.Structure):
_fields_ = [("number", ctypes.c_int),
("text", ctypes.c_char * (41))] # !!! THIS declaration is correct for C "char text [41] ;" !!!
("text", ctypes.POINTER(ctypes.c_char * (41)))] # WHICH declaration is correct for C "char text [41] ;" ?
# ("text", ctypes.POINTER(ctypes.c_char))] # WHICH declaration is correct for C "char text [41] ;" ?
# ("text", ctypes.c_char_p)] # WHICH declaration is correct for C "char text [41] ;" ?
reference = REFERENCE_STRUCT()
print("test_alloc: ", mylib.test_alloc (ctypes.byref(reference)))
print("reference.type: ", reference.type)
dataP = ctypes.cast(reference.dataP, ctypes.POINTER(DATA_STRUCT))
# accessing the number without problem:
print("dataP.contents.number: ",dataP.contents.number)
print(ctypes.cast(reference.dataP,
ctypes.POINTER(DATA_STRUCT)).contents.text)
print("test_print: ", mylib.test_print (ctypes.byref(reference)))
dataP.contents.number = 7
ctypes.cast(reference.dataP, ctypes.POINTER(DATA_STRUCT)).contents.text = b'num 6'
print("dataP.contents.number: ",dataP.contents.number)
print(ctypes.cast(reference.dataP, ctypes.POINTER(DATA_STRUCT)).contents.text)
print("test_print: ", mylib.test_print (ctypes.byref(reference)))
print("\n")
print("test_free: ", mylib.test_free (ctypes.byref(reference))) # freeing the alocated memory
列表 [Python 3.Docs]: ctypes - 一个Python的外来函数库。.
有一些问题。
DATA_STRUCT.text 定义(如你所注意到的)。应该是这样。("text", ctypes.c_char * 41)
argtypes 和 复型 外来函数的定义。主题详见 [so]: 通过ctypes从Python调用C函数,返回不正确的值(@CristiFati的答案)
访问成员。ctypes.cast(reference.dataP, ctypes.POINTER(DATA_STRUCT)).contents.text
(可将投掷指针存储在一个附加变量中,以避免多次做(写)它)