4 replies Latest Post - ‏2013-08-07T17:41:35Z by EdKlotz
2 Posts

Pinned topic Integrating CPLEX and Delphi

‏2013-07-03T12:00:56Z |

A few years ago I integrated successfully several Callable Library routines (CPLEX7.1) in programs written in Delphi 5. The objective was to solve integer linear programming problems.
Recently, through the Academic Initiative program, I updated to the IBM ILOG CPLEX 12.5 and also I updated to a new version of Delphi, Embarcadero RAD Studio XE. However I started having some problems.
Some functions called through cplex12.5.dll
continue to work well: CPXopencplex, CPXcreateprob, CPXchobjsense, CPXnewcols and CPXadrrows. The problems start when I call the solving function CPXmipopt.
I tried to use first the function CPXwriteprob but result an error 1424-Invalidate filetype. These are programs that have worked perfectly with previous versions and I also checked all the
file extensionsadmissible in CPXwriteprob.
Can anyone help me?
Attached follows a small program that aims to solve a small problem whose solution is x1 = 3, x2 = 2.
Max Z = 5x1 +4 x2
x1 + x2 <= 5
10x1 +6 x2 <= 45
x1, x2> = 0 and integers.

This program, in Delphi, use a unit CplexDLL that make the link with cplex12.5.dll callable Library.


Updated on 2013-07-03T12:01:35Z at 2013-07-03T12:01:35Z by SérgioBarreto
  • DanielJunglas
    92 Posts

    Re: Integrating CPLEX and Delphi

    ‏2013-07-03T12:23:07Z  in response to SérgioBarreto

    What you are doing here is not officially supported by CPLEX, so you are on your own ...

    It has been ages since I used pascal. I looked at this code that calls CPXwriteprob:


    Are you sure that an assignment like


    will produce the expected NUL-terminated array? Will pascal automatically add a terminating NUL byte? Can you print out MyArray3[0], MyArray3[1], MyArray3[2] to check that is the expected { 'l', 'p', NUL }? Do the same with MyArray400. You can also try to pass a null pointer as last argument of CPXwriteprob. Does that work any better?

    Updated on 2013-07-03T12:23:27Z at 2013-07-03T12:23:27Z by DanielJunglas
    • SérgioBarreto
      2 Posts

      Re: Integrating CPLEX and Delphi

      ‏2013-07-03T16:32:45Z  in response to DanielJunglas

      Dear Daniel

      I appreciate your suggestions.

      In fact, pascal automatically add a terminating NUL byte. In the above exemple I have MyArray3=('l','p',#0)and MyArray400=('P','r','o','b','l','e','m',#0,#0,#0,...);.

      I try to pass a null pointer as last argument and join the file extension in Myarray400. Doesn't work.


      The same error message, 1424-Invalid filetype.

      What intrigues me most is that all this has worked perfectly with previous versions of CPLEX and Pascal.

      Sérgio Barreto

      • DanielJunglas
        92 Posts

        Re: Integrating CPLEX and Delphi

        ‏2013-07-04T05:25:43Z  in response to SérgioBarreto

        Do you get more information about the errors on stderr if you call CPXsetintparam(env, CPX_PARAM_SCRIND, 1) right after calling CPXopenCPLEX? (CPX_PARAM_SCRIND has number 1035).

        Any chance you can use a debugger to figure out what exactly is passed into function CPXwriteprob()?

        Do other functions with string parameters work? For example CPXgetparamnum.

        Does it help to replace pCharAr400 and pCharAr3 in the definition of CPXwriteprob in CplexDLL.pas by just PChar and then call it like this:

          model : PChar;
          model = 'model.lp';
          status := CPXwriteprob(env, lp, model, Nil);


      • EdKlotz
        9 Posts

        Re: Integrating CPLEX and Delphi

        ‏2013-08-07T17:41:35Z  in response to SérgioBarreto

        I had a look, and when writing out files, error 1424 can occur for the following reasons.

        • The length of the filetype string (i.e. 4th argument in CPXwriteprob) > 3
        • The compression extension (gz, etc.) has length > 4.   Since you aren't writing a compressed file, this doesn't apply in your case.
        • The filetype string is NULL, and the file name (i.e. 3rd argument) has no '.'
        • The filetype string is NULL, and the suffix for the file name is not 'lp', 'mps' or 'sav'

        Given your description of the problem, I'd bet on some sort of trouble with the C to Delphi interface regarding handling end of string characters.   Is it possible that the new version of Delphi to which you upgraded has a different convention in this regard?    Are you familiar enough with C and a C compiler to write a very simple DLL that has a single exported function that takes a C string as argument and prints that string?   If so, you could try creating that DLL, then calling it from a simple Delphi program, and confirming that the string was passed properly.   If it wasn't, you would have a much simpler program to investigate.

        Or, has the newer version of Delphi somehow changed its convention for passing parameters to C functions?   For example, if it changed its default calling convention from stdcall to something else, and you didn't explicitly declare the CPLEX functions as stdcall, that could explain it.

        As Daniel said, Delphi access to CPLEX is unsupported.   But, if Delphi can properly call a C DLL, it should be possible to use it.    We don't have any supported information regarding calling CPLEX from Delphi, but many years ago a Delphi user kindly provided us some info regarding how to call CPLEX.  In case it helps, I have attached that file.