dotgnu-pnet
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Pnet-developers] Future of resgen


From: Carl-Adam Brengesjo
Subject: Re: [Pnet-developers] Future of resgen
Date: Fri, 21 Jan 2005 20:14:39 +0100
User-agent: Mozilla Thunderbird 1.0 (X11/20041209)

I realize this mail became more technical and longer than I first intended, but I've never been good at explaining stuff, and I'm not better at it in a language which isn't my native one. And people seems to just go "huh?" when I try to explain why we can't do other than primitive types in a unmanaged program.

For the complete list of types we can do, look in the WriteValue() method in pnetlib/runtime/Resources/ResourceWriter.cs, line 281. We can do all types except those who're being serialized, which is the last "else" block.

Gopal V wrote:
I was under the impression that .resources file is
actually a dump of the binary data in the <data>
tag (ie the <data> section contains the serialized
data itself).

We should at least support the basic case of that :)

Both yes and no, it's the same data. But also other stuff;
when the managed classes loads a bitmap from a .resx, it uses TypeConverter, I havn't looked into how TypeConverter works, but I think that this part should be fairly easy (as long as there isn't one type converter explicitly for Bitmap, meaning we can't have a general method for loading data, but we have to provide a different method for every type.

The problem as tried to describe is that serializing the object (the managed classes fully loads and create an object from the source (e.g., .resx), and then dump it to the target (e.g., .resources)), because when serializing it as binary data, extra information is provided. It actually works in a name->value way (look in BinaryValueWriter.cs, BinaryValueWriter.ObjectWriter) info provided by reflection, and other C#-ish stuff is written. This cannot be re-done in C, without a runtime engine to access the whole type definition (the IL code for the class), not just the type identifier; which is the case with resgen.

So we can hard-code the extra stuff for Bitmap and then dump the data as binary, but it isn't very flexible to support other types; in which case it's much easier (and cleaner) to do it all properly from managed space.


For those of you who isn't interested in technical stuff regarding .resources files, stop reading now.

below here is an excerpt of a hex dump from a ms.net generated .resources, followed by an excerpt from a hex dump of the base64 decoded data from the .resx used to generate the .resources file.

00001d0: 4e00 6100 6d00 6500 3a29 0100 0000 0100  N.a.m.e.:)......
00001e0: 0000 ffff ffff 0100 0000 0000 0000 0c02  ................
00001f0: 0000 0054 5379 7374 656d 2e44 7261 7769  ...TSystem.Drawi
0000200: 6e67 2c20 5665 7273 696f 6e3d 312e 302e  ng, Version=1.0.
0000210: 3530 3030 2e30 2c20 4375 6c74 7572 653d  5000.0, Culture=
0000220: 6e65 7574 7261 6c2c 2050 7562 6c69 634b  neutral, PublicK
0000230: 6579 546f 6b65 6e3d 6230 3366 3566 3766  eyToken=b03f5f7f
0000240: 3131 6435 3061 3361 0501 0000 0015 5379  11d50a3a......Sy
0000250: 7374 656d 2e44 7261 7769 6e67 2e42 6974  stem.Drawing.Bit
0000260: 6d61 7001 0000 0004 4461 7461 0702 0200  map.....Data....
0000270: 0000 0903 0000 000f 0300 0000 9428 0100  .............(..
0000280: 02ff d8ff e000 104a 4649 4600 0102 0100  .......JFIF.....

and here the first 16 bytes of the base64 decoded data from the .resx file (the <data> element).

0000000: ffd8 ffe0 0010 4a46 4946 0001 0201 0048  ......JFIF.....H

The first byte associated with the bitmap resource in the first hex dump is the 13th byte (value 0x0, total position 0x1de). This byte indicates the type from the header in the .resources file; in this case it's 0. Next follows is the actual data block, and this is large, the data associated with this resource doesn't stop until position 0x12b17.

So, if we look for the data, provided in the second hex dump, in the first one, we can look for the sequence "ffd8 ffe0", which starts at the second byte on the last line (total position 0x281). Now we can cleary see that data between 0x1de to 0x281 can't be fully provided by the .resx file alone, we need managed code to provide it. In fact, we can provide everything up to 0x263 (except for the publickeytoken etc, but that isn't required to be written anyway, to my knowledge). Data following this position is generated using reflection (MethodInfo/FieldInfo classes etc), 30 bytes to be precise. And that is the problem. There is no way a unmanaged program can properly "guess" this information based on the data provided in the .resx file. As I said, we can hardcode it for bitmap types, but that is just ugly and isn't flexible, given all the other possible data types available in .net.

If anyone still doesn't belive me, take a look yourselfs in pnetlib/runtime/System/Serialization/Formatters/Binary/BinaryValueWriter.cs starting at line 506.

Regards Carl-Adam Brengesjo.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]