Я не могу получить доступ из python ctypes (фиксированной длины) строки из ссылочной структуры, выделенной кодом C (библиотека dll). Но к типу int я могу получить доступ и изменить.
Это упрощенный код. На самом деле я использую проприетарную dll, которую не могу изменить, поэтому, пожалуйста, примите содержимое этой dll как исправленное. Я могу без проблем получить доступ к строке структуры dll из кода C - именно так я сконструировал этот пример dll, поэтому его интерфейс такой же, как интерфейс проприетарной dll.
Мое предположение было неправильным - это либо python объявление "текста" в DATA_STRUCT (перечислены различные проверенные возможности), либо способ, которым я хочу получить доступ к строке - комментируются, поскольку они либо возвращают только windows ошибка (нарушение прав доступа).
Просто обратите внимание, я использую компилятор, поставляемый с Dev-C ++ TDM-G CC 4.9.2 64-бит (который должен использовать MingW64 ) и 64 бит Python 3.8.2. Причина использования 64-битной python - это проприетарная dll, которая является 64-битной. Все ниже Windows (7).
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;
} ;
script.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