[Mono-list] marshal a struct

Norbert Lazzeri elnogge at gmx.de
Fri Oct 3 07:15:18 EDT 2008


seems like you where right. i changed the struct on the c#-side to:

/*****************/
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct INFO
{
   public int size;
   [MarshalAs(UnmanagedType.ByValArray,SizeConst=100)]
   public byte [] data;
   public bool flag;
}
/*****************/
also i found a codesnipped on the net:
/*****************/
public static string convertDllData(byte[] mybuffer){
       StringBuilder temp = new StringBuilder();
       int counter = 0;

       for(int i = 0; i < mybuffer.Length; i++){
           if(mybuffer[i] != 0x00)
           {
               temp.Append( Convert.ToChar(mybuffer[i]));
               counter++;
           }
           else{
               break;
           }
       }
       return temp.ToString();
   }
/*****************/
it does nothing else than adding only those chars to the StringBuilder 
that are not null-Characters. using this code everthing works just fine 
allthough its very ugly i think..

i also tried to convert the byte-array to a string using 
Encoding.ASCII.getString() and some other methods from Encoding but the 
problem remains here..


is this a well known bug of monodevelop or should i better file a bug?


best regards,
Norbert

Chris Howie schrieb:
> On Thu, Oct 2, 2008 at 3:54 PM, Norbert Lazzeri <elnogge at gmx.de> wrote:
>  
>> im playing around a bit with c# and dllimports.
>>
>> my unmanaged function:
>> /****************************************/
>> struct blub {
>>    int size;
>>    char data[100];
>>    bool flag;
>> };
>> /****************************************/
>> c# - calling code
>> /****************************************/
>> [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
>> public struct INFO
>> {
>>    public int size;
>>    [MarshalAs(UnmanagedType.ByValArray,SizeConst=100)]
>>    public char [] data;
>>    public bool flag;
>> }
>>
>> class MainClass
>> {
>>
>>    [DllImport ("libmitcode", CharSet = CharSet.Ansi)]
>>    private static extern int getStruct(int size, ref INFO str);
>>
>>    public static void Main(string[] args)
>>    {
>>        INFO str = new INFO();
>>        int res = getStruct(Marshal.SizeOf(str), ref str);
>>
>>        Console.Out.WriteLine(str.size);
>>        Console.Out.WriteLine(str.flag);
>>        Console.Out.WriteLine("<< " + new String(str.data) + " >>");
>>        Console.Out.WriteLine(+ res);
>>
>>    }
>> }
>> /****************************************/
>>     
>
> A couple of issues:
>
> 1. The C type char and C# type char have different sizes.  The
> marshaller is probably going to truncate going from C# to C, and
> coming back it should be filling the array with invalid (that is, not
> unicode) data.  Either store a byte[] on the C# class and use
> System.Text.Encoding.ASCII to convert, or use a string, or something.
> Somehow the String constructor or the marshaller is figuring this out
> by itself but I would not rely on this behavior, unless you can find
> where it is documented.
>
> 2. The String(char[]) constructor may not be smart enough to
> understand that a null ASCII character means end-of-string.  The
> terminal may be OK ignoring a null character, but the MD output pane
> may not, and that's why you see it truncated there.  (This is still
> arguably an MD bug, but you are correct that there are issues with
> your code as well.)
>
>   


More information about the Mono-list mailing list