Willy Denoyette [MVP]
7/12/2007 9:32:00 AM
"Jon Skeet [C# MVP]" <skeet@pobox.com> wrote in message
news:MPG.20ff36c0a1713e872d0@msnews.microsoft.com...
> Willy Denoyette [MVP] <willy.denoyette@telenet.be> wrote:
>
> <snip>
>
>> I have encountered the same issue some time ago, I guess the marshaler
>> ignores the CharSet attribute for fixed char buffers and considers the
>> unmanaged char buffer to be Ansi encoded.
>
> How bizarre. In this case, I really just want the marshaller to get out
> of the way - all it needs to do is pass in a pointer, without doing any
> extra copying. Is there any way of doing this?
>
The callee (kernel32 function) stores the value of a TimeZoneInformation
structure into the location pointed to by the caller (here to "info" on the
callers stack) .
The marshaller stays out of the picture as long as the structure contains
only blittable types, however, a *char* is non-blittable , so the marshaller
must convert the source (Unicode or MBCS) buffer to the dest *char* buffer.
This conversion occurs after the actual store of the value type, this
requires some *extra copying* of the fixed char array's (which is what you
meant I guess).
This is the point where the marshaller goes wrong (a bug!), he treats the
return buffer as a MBCS, irrespective the CharSet attribute, that means that
the conversion stops after the first character in case of a Unicode buffer.
One way to prevent this *extra copying* is to make the structure blittable
(as I illustrated).
>> Here is how I would fix it.
>>
>> public fixed byte StandardName[64]; // declare a byte type to prevent
>> the
>> marshaler to mess with the buffer (length in bytes now!)
>> ...
>> public fixed byte DaylightName[64];
>> ...
>> }
>>
>> public class Test
>> {
>>
>> ...
>> Console.WriteLine (new string((char*)info.DaylightName)); // cast
>> the byte* to char*
>> ...
>
> Yup, that appears to fix it. (I thought I'd tried something like that
> before, but apparently not.)
>
> Out of interest, have you used the new-to-C#2 fixed buffers?
We maintain company wide "Programming Guidelines" that define the usage
context of API's an features of a product (MS and others). For C# and the
FCL, we have three categories of API guidelines (the red, orange and green
books), the green book lists all API's that can safely be used in production
code, the orange book lists (annotated) all API's that need special care,
they may be used for prototyping and in "trusted" libraries, while the red
book lists the "prohibited" API's and features.
"unsafe" constructs and "fixed" are in the orange book for V2 they need some
care as they may cause unexpected behavior when used (as illustrated).
>Have you
> found them handy? I can't say I've ever used them before, as I very
> rarely touch unsafe code in the first place. Have you encountered them
> outside interop?
>
Honestly, I don't write that much code these days, but IMO they have not
much value outside interop.
Willy.