Interop Delphi dll / C# – bad memory allocation or marshaling

I’m making a wrapper to call a Delphi dll in a C# app, and I’m struggling to make it work. It doesn’t crash but the returned result is random data from memory.

I don’tknow if the problem is coming from my structures, or if it’s a problem of marshaling/unmarshaling data, or something else.

NB : I’m not the owner of the Delphi DLL, I don’t have access to the source code. All I have is these structure definition and procedure signature :

  { ////////////////////////////////////////////////////////////////////////////// }
  { ****************************************************************************** }
  { ////////////////////////////////////////////////////////////////////////////// }

  TSVADParameterInOut = record
    // Grundeinstellungen
    Sprache: Byte; { 0:deutsch 1: }
    Daten_Path: shortstring { wo die textDatei ist };
    BlendrahmenSpaltmas: integer; { Intern festgelegt auf 12,0mm. Wird nicht beachtet }
    // Kosten einstellungen
    Rabattstufensaetze: array [0 .. 8] of integer; { 0:ohne 1 Rabatt 29 /2:34 / 3:37 / 4:38 5:47 6:49 7:51 8:93 }
    // Ausgabe Daten
    Error: integer;
    Systemgrenze: integer;
  end;

  PTSVADParameterInOut = ^TSVADParameterInOut;

  { ////////////////////////////////////////////////////////////////////////////// }
  { ****************************************************************************** }
  { ////////////////////////////////////////////////////////////////////////////// }

  TSVABauteil = record
    B_Anzahl: integer;
    B_VE_Anzahl: integer;
    B_Art: integer;
    B_Preis: real;
    B_Artnr: longint;
    B_Bezeichnung: shortstring;
    B_Bezeichnung_nr: shortstring;
    B_Rabattstuffe: integer;
    B_VE_einheit: Byte;
  end;

  PTSVABauteil = ^TSVABauteil;

  TSVABauteile = array [0 .. 255] of TSVABauteil;
  PTSVABauteile = ^TSVABauteile;

  TSVABlendBauteile = array [0 .. 255] of TSVABauteil;
  PTSVABlendBauteile = ^TSVABlendBauteile;

procedure GetBauteilPreisListe(
  paramerterString: PCHAR; 
  var infoParameter: TSVADParameterInOut;
  var aPGesamtBauteile: PTSVABauteile); stdcall; external 'something.dll';

And here is the C# code :

internal class Program
{
    static void Main(string[] args)
    {
        IDataProvider provider = new DataProvider();
        var qrCode = "1001214350062700643000000143501943119471030000000400010101121001010010100000010000000210001011000000010110001000000000000000000000";

        provider.GetComponentsPriceList(qrCode);
    }
}
namespace Example
{
    public interface IDataProvider
    {
        void GetComponentsPriceList(string qrCode);
    }
}
namespace Example
{
    public class DataProvider : IDataProvider
    {
        private const string DLL_PATH = "something.dll";

        [DllImport(DLL_PATH, CallingConvention = CallingConvention.StdCall)]
        private static extern void VAD_GetBauteilPreisListe(string parameterString, ref TSVADParameterInOut infoParameter, ref IntPtr aPGesamtBauteile);


        public void GetComponentsPriceList(string qrCode)
        {
            var infoParameter = new TSVADParameterInOut();
            infoParameter.Sprache = 1;
            infoParameter.Rabattstufensaetze = new int[9];

            // Allocate unmanaged memory for the array of TSVABauteile.
            IntPtr ptrBauteile = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(TSVABauteile)));

            try
            {
                // Call the Delphi procedure.
                VAD_GetBauteilPreisListe(qrCode, ref infoParameter, ref ptrBauteile);

                // Marshal the unmanaged memory to managed structure.
                TSVABauteile bauteile = (TSVABauteile)Marshal.PtrToStructure(ptrBauteile, typeof(TSVABauteile));

                // Access the bauteile array.
                var results = new List<TSVABauteil>();
                foreach (var item in bauteile.Bauteile)
                {
                    if (item.B_Artnr != 0)
                    {
                        results.Add(item);
                        Console.WriteLine($"Art.: {item.B_Artnr} | Price: {item.B_Preis} | Desc.: {item.B_Bezeichnung}");
                    }
                }
                Console.WriteLine($"n> Count: {results.Count}"); // should return 14 elements.
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
                // Free the unmanaged memory.
                Marshal.FreeHGlobal(ptrBauteile);
            }

            Console.ReadKey();
        }
    }
}

My C# structures (

[StructLayout(LayoutKind.Sequential, Pack = 0)]
public struct TSVADParameterInOut
{
    public byte Sprache;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
    public string Daten_Path;
    public int BlendrahmenSpaltmas;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 9)]
    public int[] Rabattstufensaetze;
    public int Error;
    public int Systemgrenze;
}

[StructLayout(LayoutKind.Sequential, Pack = 0)]
public struct TSVABauteil
{
    public int B_Anzahl;
    public int B_VE_Anzahl;
    public int B_Art;
    public double B_Preis;
    public int B_Artnr;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
    public string B_Bezeichnung;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
    public string B_Bezeichnung_nr;

    public int B_Rabattstuffe;
    public byte B_VE_einheit;
}

[StructLayout(LayoutKind.Sequential, Pack = 0)]
public struct TSVABauteile
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
    public TSVABauteil[] Bauteile;
}

I have been through a lot of error (memory violation, stack overflow, unmanaged memory errors and so on) to finally come to this code that doesn’t crash, but now I can’t make any progress.

Does anybody can figure out what is wrong in this code ?


I’ve tried :

  • all structure packing sizes combinations possible from 0 to 128 for each
  • define charset as charset.Ansi
  • map Delphi shortstring into IntPtr
  • use unsafe blocks
  • don’t use ref for the aPGesamtBauteile parameter
  • Marshal the parameterString
  • an a lot of code variants like:
IntPtr ptrBauteile = Marshal.AllocHGlobal(sizeOfBauteileArray);

        try
        {
            // Initialize the memory with zeroes
            for (int i = 0; i < sizeOfBauteileArray; i++)
            {
                Marshal.WriteByte(ptrBauteile, i, 0);
            }

            // Call the Delphi procedure
            GetBauteilPreisListe(paramerterString, ref infoParameter, ref ptrBauteile);

            // Marshal the unmanaged memory to managed structure
            TSVABauteil[] managedBauteileArray = new TSVABauteil[256];
            IntPtr current = ptrBauteile;

            for (int i = 0; i < 256; i++)
            {
                managedBauteileArray[i] = (TSVABauteil)Marshal.PtrToStructure(current, typeof(TSVABauteil));
                current = IntPtr.Add(current, sizeOfBauteil);
            }

            // access the bauteile array
            foreach (var item in managedBauteileArray)
            {
                if (item.B_Artnr != 0) 
                {
                    Console.WriteLine($"B_Anzahl: {item.B_Anzahl}, B_Preis: {item.B_Preis}, B_Bezeichnung: {item.B_Bezeichnung}");
                }
            }
        }
        finally
        {
            // Free the unmanaged memory
            Marshal.FreeHGlobal(ptrBauteile);
        }

New contributor

ADM is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật