title: calling delphi dll from c#
body: <p>I have a Delphi dll defined like this:</p>
  
  <pre><code>TMPData = record
   Lastname, Firstname: array[0..40] of char;
   Birthday: TDateTime;
   Pid: array[0..16] of char;
   Title: array[0..20] of char;
   Female: Boolean;
   Street: array[0..40] of char;
   ZipCode: array[0..10] of char;
   City: array[0..40] of char;
   Phone, Fax, Department, Company: array[0..20] of char;
   Pn: array[0..40] of char;
   In: array[0..16] of char;
   Hi: array[0..8] of char;
   Account: array[0..20] of char;
   Valid, Status: array[0..10] of char;
   Country, NameAffix: array[0..20] of char;
   W, H: single;
   Bp: array[0..10] of char;
   SocialSecurityNumber: array[0..9] of char;
   State: array[0..2] of char;
  end;   
  
  function Init(const tmpData: TMPData; var ErrorCode: integer; ResetFatalError: boolean = false): boolean;
  
  procedure GetData(out tmpData: TMPData);
  </code></pre>
  
  <p>My current c# signatures looks like this:</p>
  
  <pre><code>[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
  public struct TMPData
  {            
      [MarshalAs(UnmanagedType.LPStr, SizeConst = 40)]
      public string Lastname;
      [MarshalAs(UnmanagedType.LPStr, SizeConst = 40)]
      public string Firstname;
      [MarshalAs(UnmanagedType.R8)]
      public double Birthday;
      [MarshalAs(UnmanagedType.LPStr, SizeConst = 16)]
      public string Pid;
      [MarshalAs(UnmanagedType.LPStr, SizeConst = 20)]
      public string Title;
      [MarshalAs(UnmanagedType.Bool)]
      public bool Female;
      [MarshalAs(UnmanagedType.LPStr, SizeConst = 40)]
      public string Street;
      [MarshalAs(UnmanagedType.LPStr, SizeConst = 10)]
      public string ZipCode;
      [MarshalAs(UnmanagedType.LPStr, SizeConst = 40)]
      public string City;
      [MarshalAs(UnmanagedType.LPStr, SizeConst = 20)]
      public string Phone;
      [MarshalAs(UnmanagedType.LPStr, SizeConst = 20)]
      public string Fax;
      [MarshalAs(UnmanagedType.LPStr, SizeConst = 20)]
      public string Department;
      [MarshalAs(UnmanagedType.LPStr, SizeConst = 20)]
      public string Company;
      [MarshalAs(UnmanagedType.LPStr, SizeConst = 40)]
      public string Pn;
      [MarshalAs(UnmanagedType.LPStr, SizeConst = 16)]
      public string In;
      [MarshalAs(UnmanagedType.LPStr, SizeConst = 8)]
      public string Hi;
      [MarshalAs(UnmanagedType.LPStr, SizeConst = 20)]
      public string Account;
      [MarshalAs(UnmanagedType.LPStr, SizeConst = 10)]
      public string Valid;
      [MarshalAs(UnmanagedType.LPStr, SizeConst = 10)]
      public string Status;
      [MarshalAs(UnmanagedType.LPStr, SizeConst = 20)]
      public string Country;
      [MarshalAs(UnmanagedType.LPStr, SizeConst = 20)]
      public string NameAffix;
      [MarshalAs(UnmanagedType.I4)]
      public int W;
      [MarshalAs(UnmanagedType.I4)]
      public int H;
      [MarshalAs(UnmanagedType.LPStr, SizeConst = 10)]
      public string Bp;
      [MarshalAs(UnmanagedType.LPStr, SizeConst = 9)]
      public string SocialSecurityNumber;
      [MarshalAs(UnmanagedType.LPStr, SizeConst = 2)]
      public string State;
  }
  
  [DllImport("MyDll.dll")]
  [return: MarshalAs(UnmanagedType.Bool)]
  public static extern bool Init(TMPData tmpData, int ErrorCode, bool ResetFatalError);
  
  [DllImport("MyDll.dll")]
  [return: MarshalAs(UnmanagedType.Bool)]
  public static extern bool GetData(out TMPData tmpData);
  </code></pre>
  
  <p>I first call Init setting the BirthDay, LastName and FirstName. I then call GetData but the TMPData structure I get back is incorrect. The FirstName, LastName and Birthday fields are populated but the data is incorrect. Is the mapping correct? ( "array[0..40] of char" equal to  "[MarshalAs(UnmanagedType.LPStr, SizeConst = 40)]" )?</p>
  
  <p>Update:</p>
  
  <p>I have updated the c# mapping with the feedback to look like this:</p>
  
  <pre><code>[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 
  public struct TMPData 
  {             
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 41)] 
      public string Lastname; 
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 41)] 
      public string Firstname; 
      [MarshalAs(UnmanagedType.R8)] 
      public double Birthday; 
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 17)] 
      public string Pid; 
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)] 
      public string Title; 
      [MarshalAs(UnmanagedType.Bool)] 
      public bool Female; 
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 41)] 
      public string Street; 
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)] 
      public string ZipCode; 
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 41)] 
      public string City; 
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)] 
      public string Phone; 
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)] 
      public string Fax; 
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)] 
      public string Department; 
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)] 
      public string Company; 
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 41)] 
      public string Pn; 
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 17)] 
      public string In; 
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 9)] 
      public string Hi; 
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)] 
      public string Account; 
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)] 
      public string Valid; 
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)] 
      public string Status; 
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)] 
      public string Country; 
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)] 
      public string NameAffix; 
      [MarshalAs(UnmanagedType.I4)] 
      public int W; 
      [MarshalAs(UnmanagedType.I4)] 
      public int H; 
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)] 
      public string Bp; 
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)] 
      public string SocialSecurityNumber; 
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 3)] 
      public string State; 
  } 
  </code></pre>
  
  <p>The Init function:</p>
  
  <pre><code>[DllImport("MyDll.dll")] 
  [return: MarshalAs(UnmanagedType.Bool)] 
  public static extern bool Init(TMPData tmpData, int ErrorCode, bool ResetFatalError); 
  </code></pre>
  
  <p>now fails with the following error: </p>
  
  <p>"Attempted to read or write protected memory. This is often an indication that other memory is corrupt.</p>
  
  <p>when I call it as shown below:</p>
  
  <pre><code>int errorCode = 0;
  bool resetLastError = true;
  TMPData tmpData = new TMPData();
  
          tmpData.Lastname = "TestLastName";
          tmpData.Firstname = "TestName";
          tmpData.Birthday = 28856.0;
          tmpData.Pid = "12345678";
          tmpData.Title = null;
          tmpData.Female = false;
          tmpData.Street = null; 
          tmpData.ZipCode = null;
          tmpData.City = null;
          tmpData.Phone = null;
          tmpData.Fax = null;
          tmpData.Department = null; 
          tmpData.Company = null;
          tmpData.Pn = null;
          tmpData.In = null;
          tmpData.Hi = null;
          tmpData.Account = null;
          tmpData.Valid = null;
          tmpData.Status = null;
          tmpData.Country = null;
          tmpData.NameAffix = null;
          tmpData.W = 0;
          tmpData.H = 0;
          tmpData.Bp = null;
          tmpData.SocialSecurityNumber = 0;
          tmpData.State = null;
  
  bool success = Init(tmpData, errorCode, resetLastError);    
  </code></pre>
  
  <p>If I change the ByValTStr to LPStr in the struct definition then the Init function succeeds but the GetData function returns incorrect string values. If I change LPStr back to ByValTStr the Init function fails but the GetData function returns the correct strings. I am not sure if I should marshal array[0..x] of char as LPStr of ByValTStr?</p>