DotNetNewsgroup.com  
web access to complete list of Microsoft.NET newsgroups
   home   |   control panel login   |   archive  |  
 
  carried group
academic
adonet
aspnet
aspnet.announcements
aspnet.buildingcontrols
aspnet.caching
aspnet.datagridcontrol
aspnet.mobile
aspnet.security
aspnet.webcontrols
aspnet.webservices
assignment_manager
datatools
dotnet.distributed_apps
dotnet.general
dotnet.myservices
dotnet.nternationalization
dotnet.scripting
dotnet.security
dotnet.vjsharp
dotnet.vsa
dotnet.xml
dotnetfaqs
framework
framework.clr
framework.compactframework
framework.component_services
framework.controls
framework.databinding
framework.drawing
framework.enhancements
framework.interop
framework.odbcnet
framework.performance
framework.remoting
framework.sdk
framework.setup
framework.webservices
framework.windowsforms
framework.wmi
frwk.windowsforms.designtime
lang.csharp
lang.jscript
lang.vb
lang.vb.controls
lang.vb.data
lang.vb.upgrade
lang.vc
lang.vc.libraries
  
 
start date: Tue, 10 Jul 2007 04:47:26 -0700,    posted on: microsoft.public.dotnet.framework.interop        back       

Thread Index
  1    unknown
          2    Willy Denoyette [MVP]
                 3    Jon Skeet [C# MVP]
                 4    Willy Denoyette [MVP]
                        5    Jon Skeet [C# MVP]
                        6    Willy Denoyette [MVP]
                        7    Jon Skeet [C# MVP]


C# 2 fixed sized buffers and interop   
I've just started looking into fixed sized buffers in C# 2, and I
think I must be missing something. I have no problems when not dealing
with interop, but as soon as I start using interop things go wrong.

I thought I'd try GetTimeZoneInformation as a starting point, partly
as I know I can get at the character data using
UnmanagedType.ByValTStr for a consistency check. Unfortunately, I'm
only getting the first character of the daylight name and the standard
name. A complete program follows - could someone point out the stupid
mistake I've doubtless made? Uncommenting the version using
"Marshal.As UnmanagedType.ByValTStr" gives the correct values (GMT
etc) but as posted it just prints out "G" twice.

Jon


using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential, Pack=1)]
struct SystemTime
{
  public ushort Year;
  public ushort Month;
  public ushort DayOfWeek;
  public ushort Day;
  public ushort Hour;
  public ushort Minute;
  public ushort Second;
  public ushort Milliseconds;
}

[StructLayout(LayoutKind.Sequential, Pack=1, CharSet=CharSet.Unicode)]
unsafe struct TimeZoneInformation
{
  public int Bias;
  //[MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
  //public string StandardName;
  public fixed char StandardName[32];
  public SystemTime StandardDate;
  public int StandardBias;
  //[MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
  //public string DaylightName;
  public fixed char DaylightName[32];
  public SystemTime DaylightDate;
  public int DaylightBias;
}

public class Test
{
  [DllImport("kernel32.dll", CharSet=CharSet.Unicode)]
  static extern uint GetTimeZoneInformation
    (out TimeZoneInformation timeZoneInformation);

  static void Main()
  {
      unsafe
      {
        TimeZoneInformation info;
        uint result = GetTimeZoneInformation (out info);
        //Console.WriteLine (info.StandardName);
        //Console.WriteLine (info.DaylightName);
        Console.WriteLine (new string(info.DaylightName));
        Console.WriteLine (new string(info.StandardName));
      }
  }
}
Date:Tue, 10 Jul 2007 04:47:26 -0700   Author:  

Re: C# 2 fixed sized buffers and interop   
wrote in message 
news:1184068046.501479.300280@57g2000hsv.googlegroups.com...

> I've just started looking into fixed sized buffers in C# 2, and I
> think I must be missing something. I have no problems when not dealing
> with interop, but as soon as I start using interop things go wrong.
>
> I thought I'd try GetTimeZoneInformation as a starting point, partly
> as I know I can get at the character data using
> UnmanagedType.ByValTStr for a consistency check. Unfortunately, I'm
> only getting the first character of the daylight name and the standard
> name. A complete program follows - could someone point out the stupid
> mistake I've doubtless made? Uncommenting the version using
> "Marshal.As UnmanagedType.ByValTStr" gives the correct values (GMT
> etc) but as posted it just prints out "G" twice.
>
> Jon
>
>
> using System;
> using System.Runtime.InteropServices;
>
> [StructLayout(LayoutKind.Sequential, Pack=1)]
> struct SystemTime
> {
>  public ushort Year;
>  public ushort Month;
>  public ushort DayOfWeek;
>  public ushort Day;
>  public ushort Hour;
>  public ushort Minute;
>  public ushort Second;
>  public ushort Milliseconds;
> }
>
> [StructLayout(LayoutKind.Sequential, Pack=1, CharSet=CharSet.Unicode)]
> unsafe struct TimeZoneInformation
> {
>  public int Bias;
>  //[MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
>  //public string StandardName;
>  public fixed char StandardName[32];
>  public SystemTime StandardDate;
>  public int StandardBias;
>  //[MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
>  //public string DaylightName;
>  public fixed char DaylightName[32];
>  public SystemTime DaylightDate;
>  public int DaylightBias;
> }
>
> public class Test
> {
>  [DllImport("kernel32.dll", CharSet=CharSet.Unicode)]
>  static extern uint GetTimeZoneInformation
>    (out TimeZoneInformation timeZoneInformation);
>
>  static void Main()
>  {
>      unsafe
>      {
>        TimeZoneInformation info;
>        uint result = GetTimeZoneInformation (out info);
>        //Console.WriteLine (info.StandardName);
>        //Console.WriteLine (info.DaylightName);
>        Console.WriteLine (new string(info.DaylightName));
>        Console.WriteLine (new string(info.StandardName));
>      }
>  }
> }
>



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.
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*
....

Willy.
Date:Wed, 11 Jul 2007 02:31:20 +0200   Author:  

Re: C# 2 fixed sized buffers and interop   
Willy Denoyette [MVP]  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?


> 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? 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?

-- 
Jon Skeet - 
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Date:Wed, 11 Jul 2007 19:50:13 +0100   Author:  

Re: C# 2 fixed sized buffers and interop   
"Jon Skeet [C# MVP]"  wrote in message 
news:MPG.20ff36c0a1713e872d0@msnews.microsoft.com...

> Willy Denoyette [MVP]  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.
Date:Thu, 12 Jul 2007 11:32:12 +0200   Author:  

Re: C# 2 fixed sized buffers and interop   
Willy Denoyette [MVP]  wrote:

> >> 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).


Right - in this case I want to basically tell the marshaller that it 
really *is* blittable, just get on with it.


> 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).


Right - and there's no way of doing that while still using a char 
buffer?


> > 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).

Indeed!
 
> >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.


Okay - thanks for that.

-- 
Jon Skeet - 
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Date:Thu, 12 Jul 2007 19:14:23 +0100   Author:  

Re: C# 2 fixed sized buffers and interop   
"Jon Skeet [C# MVP]"  wrote in message 
news:MPG.21007fd7cebd3f7c2d4@msnews.microsoft.com...

> Willy Denoyette [MVP]  wrote:
>> >> 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).
>
> Right - in this case I want to basically tell the marshaller that it
> really *is* blittable, just get on with it.
>
>> 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).
>
> Right - and there's no way of doing that while still using a char
> buffer?
>

It should have done it in your case (a Unicode encode struct), but it can't 
do it when the native structure holds Ansi character buffers. The Ansi 
buffer need to be *marshaled* to a fixed char buffer (Unicode only) .

Consider this sample:
a "native" Ansi encoded structure:
stuct MyNativeStruct {
    fixed char buff[16];
    int val;
}

and it's C# counterpart:
stuct MyManagedStruct {
    fixed char buff[16];
    int val;
}

here MyNativeStruct.buff is 16 bytes, while the MyManagedStruct.buff is 32 
bytes. You can't treat the structure as blittable and just pass the 
structure as is, both the char encoding and the lay-out don't match, so you 
need to marshal.

Willy.
Date:Thu, 12 Jul 2007 21:10:56 +0200   Author:  

Re: C# 2 fixed sized buffers and interop   
Willy Denoyette [MVP]  wrote:

> > Right - and there's no way of doing that while still using a char
> > buffer?
>
> It should have done it in your case (a Unicode encode struct), but it can't 
> do it when the native structure holds Ansi character buffers. The Ansi 
> buffer need to be *marshaled* to a fixed char buffer (Unicode only) .


Yup - that makes perfect sense. I was only considering the cases where 
the structure really was going to be filled with Unicode characters in 
the first place.

Hmm. I'm still looking for a really good example of using this...

-- 
Jon Skeet - 
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Date:Thu, 12 Jul 2007 21:33:09 +0100   Author:  

Google
 
Web dotnetnewsgroup.com


COPYRIGHT ?2005, EUROFRONT WORLDWIDE LTD., ALL RIGHT RESERVE  |   Contact us