2010-01-12 26 views
12

Tôi thường phải viết mã bằng các ngôn ngữ khác tương tác với cấu trúc C. Thông thường, điều này liên quan đến việc viết mã Python với các mô-đun struct hoặc ctypes.Trích xuất các trường của cấu trúc C

Vì vậy, tôi sẽ có tệp .h đầy đủ các định nghĩa cấu trúc và tôi phải đọc qua chúng một cách thủ công và sao chép các định nghĩa đó trong mã Python của tôi. Đây là thời gian và dễ bị lỗi, và rất khó để giữ cho hai định nghĩa đồng bộ khi chúng thay đổi thường xuyên.

Có một số công cụ hoặc thư viện bằng ngôn ngữ nào (không phải là C hoặc Python) có thể lấy tệp .h và tạo danh sách có cấu trúc các cấu trúc và trường của chúng? Tôi muốn có thể viết một kịch bản để tạo ra tự động của tôi tạo ra các định nghĩa struct của tôi trong Python, và tôi không muốn phải xử lý mã C tùy ý để làm điều đó. Biểu thức chính quy sẽ hoạt động tốt khoảng 90% thời gian và sau đó gây ra đau đầu vô tận cho 10% còn lại.

+3

"Cụm từ thông dụng sẽ hoạt động tốt khoảng 90% thời gian và sau đó gây đau đầu vô tận cho 10% còn lại". Là một bản tóm tắt khá tốt về Cụm từ thông dụng. Ngoại trừ tôi sẽ thực hiện tỷ lệ khoảng 50/50. – captncraig

Trả lời

10

Nếu bạn biên dịch mã C bằng cách gỡ lỗi (-g), pahole (git) có thể cung cấp cho bạn bố cục cấu trúc chính xác đang được sử dụng.

 
$ 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 */ 
}; 
… 

này nên đẹp hơn khá nhiều để phân tích hơn thẳng C.

0

Một người bạn của tôi cho công việc này đã thực hiện trình phân tích cú pháp C mà anh ấy sử dụng với cog.

3

Hãy xem Swig hoặc SIP sẽ tạo mã giao diện cho bạn hoặc sử dụng ctypes.

5

Regular expressions sẽ làm việc lớn khoảng 90% thời gian và sau đó gây đau đầu bất tận cho 10% còn lại.

Nhức đầu xảy ra trong trường hợp mã C chứa cú pháp bạn không nghĩ đến khi viết biểu thức chính quy. Sau đó, bạn quay trở lại và nhận ra rằng C không thể phân tích cú pháp bằng các biểu thức thông thường, và cuộc sống trở nên không vui vẻ.

Hãy thử chuyển nó xung quanh: xác định định dạng đơn giản của riêng bạn, cho phép ít thủ đoạn hơn so với C có, và tạo ra cả file header C và mã giao diện Python từ tập tin của bạn:

define socketopts 
    int16 port 
    int32 ipv4address 
    int32 flags 

Sau đó, bạn có thể dễ dàng viết một số Python để chuyển đổi này để:

typedef struct { 
    short port; 
    int ipv4address; 
    int flags; 
} socketopts; 

và cũng để phát ra một lớp Python trong đó sử dụng struct để đóng gói/giải nén ba giá trị (có thể là hai trong số họ lớn về cuối nhỏ và các bản địa-endian khác, tùy thuộc vào bạn) .

+0

Tôi chắc chắn đã xem xét điều này, nhưng chúng tôi thường đưa mã từ một số công ty khác mà chúng tôi cần triển khai giao thức tùy chỉnh để giao tiếp và vì chúng tôi không thể viết lại mã của họ nhưng có quyền truy cập vào tệp tiêu đề của họ 't khả thi. Tuy nhiên, nếu tôi đã thực hiện một hệ thống với cả hai thành phần C và Python từ đầu bản thân mình, tôi chắc chắn sẽ làm điều này. –

+0

Ngoài ra, tôi chỉ nhận thấy rằng ví dụ của tôi vẫn còn khá khủng khiếp, vì mã Python cần tính đến phần đệm phụ thuộc vào nền tảng giữa "cổng" và "ipv4address". Bạn có thể giải quyết "dễ bị lỗi" bằng cách sử dụng lược đồ này, dịch các tiêu đề sang DSL theo cách thủ công, và sau đó tự động tạo một số kiểm tra (được viết bằng C), đảm bảo rằng cấu trúc của bạn và cấu trúc ban đầu giống nhau, bằng cách viết các giá trị cụ thể đến các trường khác nhau của cả hai cấu trúc và sau đó ghi nhớ chúng. Sau đó kiểm tra mã Python theo cùng một cách. Nếu tất cả các trận đấu, bạn tốt. –

+1

... nếu bên thứ ba của bạn gửi cho bạn một tệp tiêu đề mà bạn không thể dịch sang DSL của mình, sau đó mở rộng DSL hoặc người khác phàn nàn ;-) Nhưng tôi thích câu trả lời ephemient, nó bị ràng buộc là ít công việc hơn, nếu chỉ vì tất cả thông tin đệm được kéo thẳng từ trình biên dịch. –

1

Tôi đã sử dụng khá thành công GCCXML trên các dự án khá lớn. Bạn nhận được một biểu diễn XML của mã C (bao gồm các cấu trúc) mà bạn có thể xử lý bằng một số Python đơn giản.

1

ctypes-codegen hoặc ctypeslib (điều tương tự, tôi nghĩ) sẽ tạo ra ctypes Structure định nghĩa (hay còn những thứ khác, tôi tin, nhưng tôi chỉ cố gắng struct) bằng cách phân tích các tập tin header sử dụng GCCXML. Nó không còn được hỗ trợ, nhưng có thể sẽ hoạt động trong một số trường hợp.

Các vấn đề liên quan