Python ctypes записывают данные для чтения исполняемым файлом C - PullRequest
0 голосов
/ 15 апреля 2020

Я пытаюсь узнать, как использовать библиотеку Python ctypes для записи данных в файл, который может быть легко прочитан исполняемыми файлами C. В небольшом тестовом примере, который я собрал, у меня возникают некоторые проблемы с чтением / записью массивов символов.

На данный момент у меня есть три исходных файла. write_struct.py создает простую структуру с двумя записями, целочисленным значением с именем git и массивом символов с именем command, затем записывает структуру в файл, используя ctypes.fwrite. read_struct.c и read_struct.h компилируются в исполняемый файл, который внутренне определяет структуру, идентичную структуре в write_struct.py, затем считывает данные, записанные сценарием python, и печатает их.

В В данный момент в файле python назначены следующие значения (буквально не так, как показано ниже, прокрутите вниз, чтобы увидеть фактический код):

git = 1
command = 'cp file1 file2'

И при запуске исполняемый файл C печатает следующее:

git: 1
command:

Я понимаю, что проблема почти наверняка заключается в том, как переменная command присваивается в сценарии python. Я прочитал, что c_char_p() (функция, которую я в настоящее время использую для инициализации данных в этой переменной) не создает указатель на изменяемую память, и вместо этого следует использовать create_string_buffer(), однако я не уверен, как это работает либо с добавлением этих данных в структуру, либо с записью их в файл. Я думаю, что я также запутался в том, как в первую очередь работает запись указателей / их данных в файл. Каков лучший способ go сделать это?

Заранее спасибо всем, кто сможет помочь !!

Код моих трех файлов приведен ниже для справки:

write_struct.py:

"""
write_struct.py
"""

from ctypes import *

libc = cdll.LoadLibrary("libc.so.6")

class DataStruct(Structure):
    _fields_ = [("git", c_int),
                ("command", c_char_p)
                ]

def main():
    pydata = DataStruct(1, c_char_p("cp file1 file2"))

    libc.fopen.argtypes = c_char_p, c_char_p
    libc.fopen.restype = c_void_p

    libc.fwrite = libc.fwrite
    libc.fwrite.argtypes = c_void_p, c_size_t, c_size_t, c_void_p
    libc.fwrite.restype = c_size_t

    libc.fclose = libc.fclose
    libc.fclose.argtypes = c_void_p,
    libc.fclose.restype = c_int


    f = libc.fopen("stored_data", "wb")
    libc.fwrite(byref(pydata), sizeof(pydata), 1, f)
    libc.fclose(f)
    return 0

main()

read_struct.c:

/*
 * read_struct.c
 *
 */

#include "read_struct.h"

int main()
{
  data_struct cdata = malloc(DATASIZE);
  FILE *fp;
  if ((fp = fopen("stored_data", "r")) != NULL) {
    fread(cdata, DATASIZE, 1, fp);
    printf("git: %i\n", cdata->git);
    printf("command:");
    printf("%s\n", cdata->command);
    fclose(fp);
  } else {
    printf("Could not open file\n");
    exit(1);
  }
  return 0;
}

read_struct.h:

/*
 * read_struct.h
 *
 */

#include <stdio.h>
#include <stdlib.h>

typedef struct _data_struct *data_struct;
struct _data_struct {
  int git;
  char command[40];
};
#define DATASIZE sizeof(struct _data_struct)

1 Ответ

1 голос
/ 16 апреля 2020

Вы можете записать двоичные данные напрямую с помощью Python. ctypes может использоваться для создания структуры и поддержки битовых полей и объединений, или для простых структур может использоваться модуль struct.

from ctypes import *

class DataStruct(Structure):
    _fields_ = [("git", c_int),
                ("command", c_char * 40)] # You want array here, not pointer

pydata = DataStruct(1,b'cp file1 file2')  # byte string for initialization.
with open('stored_data','wb') as f:       # write file in binary mode
    f.write(pydata)                       # ctypes support conversion to bytes
import struct

# See struct docs for formatting codes
# i = int (native-endian.  Use <i to force little-endian, >i for big-endian)
# 40s = char[40] (zero-padded if initializer is shorter)
pydata = struct.pack('i40s',1,b'cp file1 file2')
with open('stored_data2','wb') as f:
    f.write(pydata)

Ссылка: https://docs.python.org/3/library/struct.html#format -струны

...