आप कहो निम्नलिखित module.h
:
#! /usr/bin/perl
use warnings;
use strict;
sub usage { "Usage: $0 header\n" }
structs
के साथ, हम ctags
करने के लिए और से हैडर फ़ीड:
typedef void (*handler)(void);
struct foo {
char a;
double b;
int c;
};
struct bar {
float y;
short z;
};
एक पर्ल unpack
टेम्पलेट्स उत्पन्न करने के लिए कार्यक्रम प्रथागत सामने बात के साथ शुरू होता इसके उत्पादन संरचना सदस्यों को इकट्ठा करते हैं। परिणाम एक हैश है जिनकी चाबियाँ structs के नाम हैं और जिनके मान [$member_name, $type]
रूप के जोड़े के सरणी हैं।
ध्यान दें कि यह केवल कुछ सी प्रकारों को संभालता है।
sub structs {
my($header) = @_;
open my $fh, "-|", "ctags", "-f", "-", $header
or die "$0: could not start ctags";
my %struct;
while (<$fh>) {
chomp;
my @f = split /\t/;
next unless @f >= 5 &&
$f[3] eq "m" &&
$f[4] =~ /^struct:(.+)/;
my $struct = $1;
die "$0: unknown type in $f[2]"
unless $f[2] =~ m!/\^\s*(float|char|int|double|short)\b!;
# [ member-name => type ]
push @{ $struct{$struct} } => [ $f[0] => $1 ];
}
wantarray ? %struct : \%struct;
}
यह मानते हुए कि शीर्ष लेख अपने आप में शामिल किया जा सकता, generate_source
एक सी प्रोग्राम है जो मानक आउटपुट में ऑफसेट प्रिंट, डमी मूल्यों के साथ structs भरता उत्पन्न करता है, और मानक उत्पादन अपने-अपने आकार से पहले करने के लिए कच्चे संरचनाओं लिखते हैं बाइट्स में
sub generate_source {
my($struct,$header) = @_;
my $path = "/tmp/my-offsets.c";
open my $fh, ">", $path
or die "$0: open $path: $!";
print $fh <<EOStart;
#include <stdio.h>
#include <stddef.h>
#include <$header>
void print_buf(void *b, size_t n) {
char *c = (char *) b;
printf("%zd\\n", n);
while (n--) {
fputc(*c++, stdout);
}
}
int main(void) {
EOStart
my $id = "a1";
my %id;
foreach my $s (sort keys %$struct) {
$id{$s} = $id++;
print $fh "struct $s $id{$s};\n";
}
my $value = 0;
foreach my $s (sort keys %$struct) {
for (@{ $struct->{$s} }) {
print $fh <<EOLine;
printf("%lu\\n", offsetof(struct $s,$_->[0]));
$id{$s}.$_->[0] = $value;
EOLine
++$value;
}
}
print $fh qq{printf("----\\n");\n};
foreach my $s (sort keys %$struct) {
print $fh "print_buf(&$id{$s}, sizeof($id{$s}));\n";
}
print $fh <<EOEnd;
return 0;
}
EOEnd
close $fh or warn "$0: close $path: $!";
$path;
}
जहां पैरामीटर $members
कि ऑफसेट (यानी, प्रपत्र [$member_name, $type, $offset]
की arrayrefs साथ संवर्धित किया गया है हैश structs
द्वारा वापस में एक मूल्य है unpack
के लिए खाका तैयार करें:
sub template {
my($members) = @_;
my %type2tmpl = (
char => "c",
double => "d",
float => "f",
int => "i!",
short => "s!",
);
join " " =>
map '@![' . $_->[2] . ']' . $type2tmpl{ $_->[1] } =>
@$members;
}
अंत में , हम मुख्य कार्यक्रम तक पहुंचते हैं जहां पहला कार्य सी प्रोग्राम को उत्पन्न और संकलित करना है:
die usage unless @ARGV == 1;
my $header = shift;
my $struct = structs $header;
my $src = generate_source $struct, $header;
(my $cmd = $src) =~ s/\.c$//;
system("gcc -I`pwd` -o $cmd $src") == 0
or die "$0: gcc failed";
अब हम उत्पन्न कार्यक्रम के उत्पादन को पढ़ने और structs डिकोड:
my @todo = map @{ $struct->{$_} } => sort keys %$struct;
open my $fh, "-|", $cmd
or die "$0: start $cmd failed: $!";
while (<$fh>) {
last if /^-+$/;
chomp;
my $m = shift @todo;
push @$m => $_;
}
if (@todo) {
die "$0: unfilled:\n" .
join "" => map " - $_->[0]\n", @todo;
}
foreach my $s (sort keys %$struct) {
chomp(my $length = <$fh> || die "$0: unexpected end of input");
my $bytes = read $fh, my($buf), $length;
if (defined $bytes) {
die "$0: unexpected end of input" unless $bytes;
print "$s: @{[unpack template($struct->{$s}), $buf]}\n";
}
else {
die "$0: read: $!";
}
}
आउटपुट:
$ ./unpack module.h
bar: 0 1
foo: 2 3 4
संदर्भ के लिए, सी module.h
के लिए उत्पन्न कार्यक्रम है
#include <stdio.h>
#include <stddef.h>
#include <module.h>
void print_buf(void *b, size_t n) {
char *c = (char *) b;
printf("%zd\n", n);
while (n--) {
fputc(*c++, stdout);
}
}
int main(void) {
struct bar a1;
struct foo a2;
printf("%lu\n", offsetof(struct bar,y));
a1.y = 0;
printf("%lu\n", offsetof(struct bar,z));
a1.z = 1;
printf("%lu\n", offsetof(struct foo,a));
a2.a = 2;
printf("%lu\n", offsetof(struct foo,b));
a2.b = 3;
printf("%lu\n", offsetof(struct foo,c));
a2.c = 4;
printf("----\n");
print_buf(&a1, sizeof(a1));
print_buf(&a2, sizeof(a2));
return 0;
}
मैं डॉन ' आप समझ रहे हैं कि आप क्या पूछ रहे हैं। क्या आप सी भाषा के लिए एक सामान्य प्रतिबिंब प्रणाली बनाना चाहते हैं? सी में प्रतिबिंब चाहते हैं एक मोटरबाइक के साथ अटलांटिक महासागर पार करना चाहते हैं ... –
क्षमा करें अगर मैं अपने प्रश्न में स्पष्ट नहीं था। मैं एक सामान्य प्रतिबिंब प्रणाली की तलाश नहीं कर रहा हूं (मुझे उम्मीद है!)। मुझे लगा कि मेरे समाधान में सीएल स्रोत कोड को पर्ल के साथ पार्स करना होगा और कुछ संशोधित सी कोड को संरचना में प्रत्येक तत्व के लिए आकार और ऑफसेट कॉल के साथ उत्पन्न करना होगा।इससे संरचना में सभी तत्वों का आकार और स्थान प्रदान किया जाएगा, और इससे संरचना में शामिल किसी भी पैडिंग को ढूंढना और रिपोर्ट करना मुश्किल है। क्या यह एक उचित दृष्टिकोण की तरह प्रतीत होता है, या आप समस्या के बारे में एक अलग तरीके से जाना होगा? –