Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   load a dll at run-time (https://www.delphipraxis.net/177789-load-dll-run-time.html)

tony.huerlimann 27. Nov 2013 14:21

Delphi-Version: 5

load a dll at run-time
 
I have a strange problem when loading a dll at run-time into Delphi. The following correct Dephi code:

1) loads a dll (gurobi55.dll) at run-time
2) sets three pointers to three functions into the dll
3) runs the three dll functions and exits

Normally this code runs well: it reads a mathematical model from a file and
solves it by optimizing a function defined in the file. The result is then stored in a
second file 'gurobi.log' and the programm exits.

Now the file 'ALUAM.mps' defines a large model (450MB) with 3200000 variables. Normally, it is
no problem for the commercial solver Gurobi to solve such problems. However, Delphi
(XE2 and XE5, 64bit) crashed some time after calling GRBoptimize() with a FLOATING POINT ERROR.

If I run an identical code in C++ Builder (XE5, 64bit) it runs fine.
My question: Is there a fundamental difference between Delphi(Pascal) and C++ Builder
in loading and running dll Functions? Is there a memory limitation in Delphi's handling
of a dll memory storage? Or what could be the problem here?

The two complete programs are as follows (by the way these two code snippets
shows also --for the novice-- how to implement dynamically loading libraries in Windows (dll)
in Delphi AND in C++ Builder).


------------------ BEGIN DELPHI CODE XE5, 64bit compiler ---------
Delphi-Quellcode:
program GurobiTest;
{$APPTYPE CONSOLE}
uses System.SysUtils, Windows;

label QUIT;
type pAChar  = pAnsiChar;
      GRBenv  = pointer;
      GRBmodel = pointer;

var  h:HMODULE; err:integer;
      grEnv:GRBenv;
      grLp:GRBmodel;

   GRBloadenv: function(var envP:GRBenv; logfilename:pAChar):integer; stdcall;
   GRBreadmodel: function(env:GRBenv; filename:pAChar; var mp:GRBmodel):integer; stdcall;
   GRBoptimize: function(model:GRBmodel):integer; stdcall;

begin
  h:=LoadLibrary('C:/gurobi550/win64/bin/gurobi55.dll');
  GRBloadenv := GetProcAddress(h,'GRBloadenv');
  GRBreadmodel := GetProcAddress(h,'GRBreadmodel');
  GRBoptimize := GetProcAddress(h,'GRBoptimize');

  err:= GRBloadenv(grEnv, 'gurobi.log');
  if err<>0 then goto QUIT;

  err:=GRBreadmodel(grEnv,'ALUAM.mps',grLp);
  if err<>0 then goto QUIT;

  err:= GRBoptimize(grLp);
  if err<>0 then goto QUIT;

  QUIT:
  FreeLibrary(h);
end
------------------ END DELPHI CODE -------------------------------


----------- BEGIN C++ CODE: C++ Builder XE5, 64bit compiler -------
Code:
#pragma hdrstop
#pragma argsused

#include <tchar.h>
#include <stdio.h>

#include <windows.h>

typedef void* GRBmodel;

typedef void* GRBenv;

typedef char* pAChar;

typedef int (__stdcall* sGurobi__0)(GRBenv& envp, pAChar LogFileName);
sGurobi__0 GRBloadenv;;

typedef int (__stdcall* sGurobi__1)(GRBmodel model, pAChar AttrName, GRBmodel& modelp);
sGurobi__1 GRBreadmodel;;

typedef int ( __stdcall * sGurobi__2 )(GRBmodel model);
sGurobi__2 GRBoptimize;;

int _tmain(int argc, _TCHAR* argv[])
{
   int err;
   HMODULE hdll = NULL;
   GRBenv grEnv = NULL;
   GRBmodel grLp = NULL;

   hdll = LoadLibrary("C:\\gurobi550\\win64\\bin\\gurobi55.dll");
   err=GetLastError();
   if (err) goto QUIT;

   GRBloadenv = (sGurobi__0) GetProcAddress( hdll, "GRBloadenv" );
   GRBreadmodel = (sGurobi__1) GetProcAddress(hdll,"GRBreadmodel");
   GRBoptimize = (sGurobi__2) GetProcAddress(hdll,"GRBoptimize");

   err = GRBloadenv(grEnv, "gurobi.log");
   if (err) goto QUIT;

  err = GRBreadmodel(grEnv,"ALUAM.mps",grLp);
  if (err) goto QUIT;

  err = GRBoptimize(grLp);
  if (err) goto QUIT;

QUIT:
   FreeLibrary(hdll);
   return 0;
}
-------------------------------------- END C++ CODE --------------

Thanks for help
Tony

baumina 27. Nov 2013 15:21

AW: load a dll at run-time
 
Take a look at http://docwiki.embarcadero.com/RADSt...e_Applications

Zitat:

Console applications are 32-bit programs that run without a graphical interface, in a console window, on a target platform.
I think it isnt 64-bit.

lbccaleb 27. Nov 2013 17:46

AW: load a dll at run-time
 
Do you really still use jump marks?

A example how you can dynamically load a Libary can you find here:
http://www.delphipraxis.net/175591-d...ml#post1220503

Edit1:
Btw, you have to link external Posts:
http://forum.delphi-treff.de/index.p...threadID=59293


Edit2:
Delphi-Quellcode:
program GurobiTest;
{$APPTYPE CONSOLE}
uses System.SysUtils, Windows;

//label QUIT;
type
  pAChar  = pAnsiChar;
  GRBenv  = pointer;
  GRBmodel = pointer;

var
  h:    HMODULE;
  err:  integer;
  grEnv: GRBenv;
  grLp: GRBmodel;

   GRBloadenv:  function(var envP:GRBenv; logfilename:pAChar):integer; stdcall;
   GRBreadmodel: function(env:GRBenv; filename:pAChar; var mp:GRBmodel):integer; stdcall;
   GRBoptimize: function(model:GRBmodel):integer; stdcall;

begin;
 
  h := LoadLibrary('C:/gurobi550/win64/bin/gurobi55.dll');
  if h = 0 then begin;
    ShowMessage('Cannot load dll');
    Exit;
  end;

  GRBloadenv := GetProcAddress(h,'GRBloadenv');
  GRBreadmodel := GetProcAddress(h,'GRBreadmodel');
  GRBoptimize := GetProcAddress(h,'GRBoptimize');

  if Assigned(GRBloadenv) then begin;
    err := GRBloadenv(grEnv, 'gurobi.log');
    if err <> 0 then
      //MessageBox?
  end;

  if Assigned(GRBreadmodel) then begin;
    err := GRBreadmodel(grEnv, 'ALUAM.mps', grLp);
    if err <> 0 then
      //MessageBox?
  end;

  if Assigned(GRBoptimize) then begin;
    err := GRBoptimize(grLp);
    if err <> 0 then
      //MessageBox?
  end;

  FreeLibrary(h);
end.
-->not testet :D

tony.huerlimann 28. Nov 2013 08:19

AW: load a dll at run-time
 
problem resolved
Ed Rothberg from Gurobi gave me the answer that I can post here. He wrote:

The answer is contained in this Stack Overflow post...
http://stackoverflow.com/questions/1...nd-twebbrowser

The
quick summary: 1.0/0.0 gives a +Inf result in nearly every language.
In Delphi, it gives an exception. There's something in your input data
that is causing a divide-by-zero within the Gurobi library.
If
you send us 'ALUAM.mps', we can look at where the divide-by-zero is
coming from. The simple fix is to turn off divide-by-zero exceptions in
Delphi (SetExceptionMask(GetExceptionMask()+ [exZeroDivide]).
Ed
I checked it out. In the Delphi code above. I added the instruction before LoadLibrary() as follows. Add also "Math" in the uses list:


Delphi-Quellcode



begin
SetExceptionMask(GetExceptionMask() + [exZeroDivide]);
h:=LoadLibrary('C:/gurobi550/win64/bin/gurobi55.dll');
.....



Thank you Ed
Tony

Der schöne Günther 28. Nov 2013 09:47

AW: load a dll at run-time
 
Nice. I never would have guessed.


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:18 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz