Извлечь поля структуры C
Мне часто приходится писать код на других языках, которые взаимодействуют с C-структурами. Как правило, это связано с написанием кода Python с struct или ctypes.
Итак, у меня будет файл .h, полный описаний структуры, и я должен вручную прочитать их и дублировать эти определения в моем коде Python. Это отнимает много времени и подвержено ошибкам, и сложно синхронизировать два определения при их частом изменении.
Есть ли какой-нибудь инструмент или библиотека на любом языке (не обязательно должен быть C или Python), который может взять файл .h и создать структурированный список его структур и их полей? Мне бы хотелось написать script, чтобы автоматически генерировать мои определения struct в Python, и я не хочу обрабатывать произвольный код C для этого. Регулярные выражения будут работать отлично в 90% случаев, а затем вызывать бесконечные головные боли для остальных 10%.
Ответы
Ответ 1
Если вы скомпилируете свой код C с отладкой (-g
), pahole (git) может дать вам точные структуры структуры, которые используются.
$ pahole /bin/dd
…
struct option {
const char * name; /* 0 8 */
int has_arg; /* 8 4 */
/* XXX 4 bytes hole, try to pack */
int * flag; /* 16 8 */
int val; /* 24 4 */
/* size: 32, cachelines: 1, members: 4 */
/* sum members: 24, holes: 1, sum holes: 4 */
/* padding: 4 */
/* last cacheline: 32 bytes */
};
…
Это должно быть намного лучше, чем синтаксический анализ.
Ответ 2
Регулярные выражения будут работать отлично в 90% случаев, а затем вызывать бесконечные головные боли для остальных 10%.
Головные боли случаются в случаях, когда код C содержит синтаксис, о котором вы не думали при написании регулярных выражений. Затем вы возвращаетесь и понимаете, что C не может быть проанализирован регулярными выражениями, и жизнь становится не весело.
Попробуйте повернуть его: определите свой собственный простой формат, который позволяет меньше трюков, чем C, и генерирует как файл заголовка C, так и код интерфейса Python из вашего файла:
define socketopts
int16 port
int32 ipv4address
int32 flags
Затем вы можете легко написать Python, чтобы преобразовать его в:
typedef struct {
short port;
int ipv4address;
int flags;
} socketopts;
а также выпустить класс Python, который использует struct
для упаковки/распаковки трех значений (возможно, двух из них - big-endian и другого native-endian, до вас).
Ответ 3
Посмотрите Swig или SIP, который будет генерировать код интерфейса для вас или использовать ctypes.
Ответ 4
Вы посмотрели Swig?
Ответ 5
Я довольно успешно использовал GCCXML в довольно больших проектах. Вы получаете XML-представление кода C (включая структуры), которое вы можете выполнить после обработки с помощью простого Python.
Ответ 6
ctypes-codegen или ctypeslib (тот же вещь, я думаю) будет генерировать определения ctypes Structure
(также, я полагаю, другие вещи, но я только пробовал структуры), анализируя файлы заголовков с помощью GCCXML. Он больше не поддерживается, но, вероятно, будет работать в некоторых случаях.
Ответ 7
Один мой друг для этих задач выполнил C-парсер, который он использует с cog.