2

I need to uncompress large gzip file (more than 4.5 Go). I've got some trouble to do this with Delphi Seattle using the TDecompressionStream (Result file is truncated).

To avoid this problem, I choose to do this task in a C# dll and to call it from Delphi.

My C# code is working, I test it wiht a console application. I add the nugget package UnmanagedExports and compile the dll in 32 bits.

When I call my dll method from Delphi, I've got this error : "External exception E0434352"

I follow advices of this links : How to use a DLL created with C# in Delphi

but I already have this problem

My c# code

    static public class UnZip
    {
        [DllExport("UngzipFile", CallingConvention.StdCall)]
        public static int UngzipFile(string aFile)
        {
            int result = 0;
            FileInfo fileInfo = new FileInfo(aFile);
            using (FileStream fileToDecompress = fileInfo.OpenRead())
            {
                string decompressedFileName = Path.Combine(Path.GetDirectoryName(aFile), "temp.sql");
                using (FileStream decompressedStream = File.Create(decompressedFileName))
                {
                    using (GZipStream decompressionStream = new GZipStream(fileToDecompress, CompressionMode.Decompress))
                    {
                        try
                        {
                            decompressionStream.CopyTo(decompressedStream);
                        }
                        catch
                        {
                            result = 1;                            
                        }
                    }
                }
            }
            return result;
        }
    }

My Delphi code

function UngzipFile(aFile : string) : Integer; stdcall; external 'UnCompress.dll';

procedure TForm1.UnzipFile(aFileName: String);
var
  UnZipFileName : string;
  Return : integer;
  DllZipFile : PWideChar;
begin
  UnZipFileName := ExtractFilePath(aFileName)+'Temp.sql';

  if FileExists(UnZipFileName) then
    DeleteFile(UnZipFileName);

  DllZipFile := PWideChar(aFileName);
  Return := UngzipFile(DllZipFile);
  if Return > 0 then
    raise Exception.Create('Error while uncompressing file');
end;

For the moment, when I call UngzipFile from Delphi, _I've got the external exception E0434352.

I expect to have result = 0 and my file to be uncompress.

Thanks for your help.

Toine Gva
  • 49
  • 1
  • 4
  • 1
    Obviously, your C# DLL causes an exception and Delphi can't handle such an exception. Ensure that your DLL can't raise an exception. Exceptions should **never, ever** leave a DLL, no matter in which language it was written. – Rudy Velthuis Mar 29 '19 at 07:27
  • FWIW: http://rvelthuis.de/articles/articles-dlls.html#exceptions – Rudy Velthuis Mar 29 '19 at 07:41

1 Answers1

2

There was an exception in my DLL because of the string parameter. I add log in the dll and I found that there was only the first character of my parameter which was took by the dll.

This post Using a C# DLL in Delphi only uses the first function parameter help me to correct my code.

New C# code

    static public class UnZip
    {
        [DllExport("UngzipFile", CallingConvention.StdCall)]
        public static int UngzipFile([MarshalAs(UnmanagedType.LPWStr)] string aFile)
        {
            if (!File.Exists(aFile))
                return 3;

            FileInfo fileInfo;

            string logFile = @"D:\Temp\logDll.log";            
            try
            {
                File.AppendAllText(logFile, aFile);
                fileInfo = new FileInfo(aFile);
            }
            catch(Exception ex)
            {
                File.AppendAllText(logFile, String.Format("File : {0} || Exception : {1}",aFile,ex.Message));
                return 2;
            }

            int result = 0;
            using (FileStream fileToDecompress = fileInfo.OpenRead())
            {
                string decompressedFileName = Path.Combine(Path.GetDirectoryName(aFile), "temp.sql");
                using (FileStream decompressedStream = File.Create(decompressedFileName))
                {
                    using (GZipStream decompressionStream = new GZipStream(fileToDecompress, CompressionMode.Decompress))
                    {
                        try
                        {
                            decompressionStream.CopyTo(decompressedStream);
                        }
                        catch
                        {
                            result = 1;                            
                        }
                    }
                }
            }
            return result;
        }
    }

By adding [MarshalAs(UnmanagedType.LPWStr)] in my parameter declaration, this resolve the problem.

TylerH
  • 20,799
  • 66
  • 75
  • 101
Toine Gva
  • 49
  • 1
  • 4
  • 1
    This is still wrong. The Delphi code needs to be declared like this: `function UngzipFile(aFile : PWideChar) : Integer; stdcall; external 'UnCompress.dll';` Then call it like this: `Return := UngzipFile(PChar(DllZipFile));` – David Heffernan Mar 29 '19 at 10:52