title: How to call Delphi DLL from C# (Method's type signature is not PInvoke compatible error)?
body: <p>I have some Delphi code which is currently calling a DLL (also written in Delphi). Here is the Delphi code:</p>
  
  <pre><code>    TDLLDataHeader = record
          s                   : string[255];
          i                   : integer;
          stage               : integer;
          number_of_fields    : integer;
          sample_code         : string[255];
          comment             : string[255];
      end;
  
      TPassword_rec = record
          level               : byte;
          User_ID             : string[20];
          Signature           : string[80];
      end;
  
      TField_result  = packed record        {Packed added to make size compatible with Delphi4}
          area                        : double;
          count                       : longint;
          frame_area                  : double;
          perimeter                   : double;  { currently 0}
          total_object_grey_level     : comp;
          total_framed_grey_level     : comp;
          pixel_area                  : comp;
          pixel_frame_area            : comp;
          mean_object_grey_level      : double;
          mean_framed_grey_level      : double;
          no_of_excluded_objects      : longint;
          ppm                         : double;
          total_ppm                   : double;
          ppm_squared                 : double;
      end;
  
      Tfeature_summary  = packed record  {Packed added to make size compatible with Delphi4}
          total_eba              : double;
          eba_ppm                : double;
          eba_ppm_squared        : double;
          total_object_area      : double;
          total_perimeter        : double;
          total_grey_level       : longint;
          ppm                    : double;
          total_ppm              : double;
          ppm_squared            : double;
      end;
  
      Tshortmeasurement   = record
          sample_code              : string[255];
          comment                  : string[255];
          datetime                 : Tdatetime;
          measured_by              : string[20];
          dilution                 : double;
          calibration_factor_used  : double;
          field                    : Tfield_result;
          feature                  : Tfeature_summary;
          detection_mode           : integer; {25/8/00 detection settings added to measurement data}
          straight_threshold       : byte;
          matrix_threshold         : byte;
          matrix_size              : byte;
          Count_per_plate          : integer;
      end;
  
  procedure GetDLLData_header(var Aheaderdata : PDllDataHeader); stdcall; external 'remote.dll' name 'GetDLLData';
            { reads global data pointer back fronm the dll}
  function get_data : Tshortmeasurement; stdcall; external 'remote.dll' name 'get_data';
  function get_macro_status : byte; stdcall; external 'remote.dll' name 'get_macro_status';
  function send_msg_to_host(lparam,wparam : longint) : longint; stdcall; external 'remote.dll' name 'send_msg_to_host';
  function get_no_of_measurements : integer; stdcall; external 'remote.dll' name 'get_no_of_measurements';
  </code></pre>
  
  <p>Further on in the Delphi code there is a call to get_data:</p>
  
  <pre><code>var
      Temp_data : Tshortmeasurement;
  begin
      temp_data := get_data;
  end;
  </code></pre>
  
  <p>I am trying to recreate this in C# but I am getting a "Method's type signature is not PInvoke compatible error".</p>
  
  <p>Here is my C# code:</p>
  
  <pre><code>[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
  public struct TField_result
  {
      //area                        : double;
      public double area;
      //count                       : longint;
      public int count;
      //frame_area                  : double;
      public double frame_area;
      //perimeter                   : double;  { currently 0}
      public double perimeter;
      //total_object_grey_level     : comp;
      public double total_object_grey_level;
      //total_framed_grey_level     : comp;
      public double total_framed_grey_level;
      //pixel_area                  : comp;
      public double pixel_area;
      //pixel_frame_area            : comp;
      public double pixel_frame_area;
      //mean_object_grey_level      : double;
      public double mean_object_grey_level;
      //mean_framed_grey_level      : double;
      public double mean_framed_grey_level;
      //no_of_excluded_objects      : longint;
      public int no_of_excluded_objects;
      //ppm                         : double;
      public double ppm;
      //total_ppm                   : double;
      public double total_ppm;
      //ppm_squared                 : double;
      public double ppm_squared;
  }
  
  [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
  public struct TFeature_summary
  {
      //total_eba              : double;
      public double total_eba;
      //eba_ppm                : double;
      public double eba_ppm;
      //eba_ppm_squared        : double;
      public double eba_ppm_squared;
      //total_object_area      : double;
      public double total_object_area;
      //total_perimeter        : double;
      public double total_perimeter;
      //total_grey_level       : longint;
      public int total_grey_level;
      //ppm                    : double;
      public double ppm;
      //total_ppm              : double;
      public double total_ppm;
      //ppm_squared            : double;
      public double ppm_squared;
  }
  
  
  [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
  public struct Tshortmeasurement
  {
      //sample_code              : string[255];
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
      public string sample_code;
      //comment                  : string[255];
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
      public string comment;
      //datetime                 : Tdatetime;
      public double datetime;
      //measured_by              : string[20];
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
      public string measured_by;
      //dilution                 : double;
      public double dilution;
      //calibration_factor_used  : double;
      public double calibration_factor_used;
      //field                    : Tfield_result;
      public TField_result field;
      //feature                  : Tfeature_summary;
      public TFeature_summary feature;
      //detection_mode           : integer;
      public int detection_mode;
      //straight_threshold       : byte;
      public byte straight_threshold;
      //matrix_threshold         : byte;
      public byte matrix_threshold;
      //matrix_size              : byte;
      public byte matrix_size;
      //Count_per_plate          : integer;
      public int Count_per_plate;
  }
  
  
  class Program
  {
  
  
      [DllImport("remote.dll", SetLastError = true, CharSet = CharSet.Auto)]
      public static extern UIntPtr send_msg_to_host(
          IntPtr lParam,
          UIntPtr wParam
      );
      [DllImport("remote.dll", SetLastError = true, CharSet = CharSet.Auto)]
      public static extern int get_no_of_measurements();
  
      [DllImport("remote.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto)]
      public static extern Tshortmeasurement get_data();
  
      static void Main(string[] args)
      {
          int n = get_no_of_measurements();
          get_data();
          Console.WriteLine(n.ToString());
          Console.ReadLine();
      }
  }
  </code></pre>
  
  <p>The call to get_no_of_measurements works fine, but the call to get_data results in the error mentioned previously. I have researched about "marshalling" and I think that must be the cause, possibly relating to the TFeature_summary and TField_result structs. I am fairly new to C# so apologies if I have missed something obvious!</p>