Calling the lpsolve API from your application

There are two ways to call the lpsolve API from an application:

  • Statically
  • Dynamically

Statically means that the lpsolve code is statically linked to the code. This means that the program does not need extra files to be able to call lpsolve since the code is already contained in the executable. The executable will thus be larger. This can only be done if you have the source code of your program and you can recompile it and link it with the lpsolve code. Not all programming languages have the possibility to statically link code. For example VB6 does not have a way to do that. The advantage of this way of calling the lpsolve library is that you don't have to provide extra files with your executable since the library is already in the exe. The disadvantage is that you must recompile (or at least link) the program with the lpsolve code when an update of lpsolve is needed. There are two ways to link your application with the lpsolve code. The first way is add the needed lpsolve source code to the project and compile it together as one unit. This is most probably only possible when the code is also written in C/C++ (however not always since for example .NET allows to link for example C# code with C code). The disadvantage of this way of working is that you have to revise your project when you use a new version of lpsolve since there could be files added or removed in the lpsolve package. Also you may have to define some defines. A better way of working is making use of the lpsolve library. Under DOS/Windows this is called lpsolve5.lib, under Unix/Linux liblpkit5.a. The advantages are that other languages (like Pascal) can also link with such a library, your project is not overloaded with the lpsolve source files and also not unimportant, the linker only takes the code from the library that you really use resulting in a smaller executable. One disadvantage is that you cannot debug and step trough the lpsolve code then, if you would want to do that.

Dynamically means that the lpsolve code is dynamically linked to your code. This means that it is linked to your program when the executable is started or even only when you make calls to the lpsolve library. The lpsolve library is then not linked with the executable and is provided in a separate file. Under Windows this is a dll (lpsolve5.dll), under Unix/Linux this is a shared library (liblpkit5.so). You must distribute this separate library with your program to make it work. The library must be located on a place that can be found by the program. There are several advantages of this way of working. Almost all programming languages have a way to call dynamic libraries or even can only call libraries that way. One example is VB6. Another advantage is that it is easier to update the package. The program doesn't have to be recompiled/relinked. You only have to provide a new lpsolve library.

Needed sources files

The following source files must at least be added to your project:

colamd/colamd.c
commonlib.c
lp_MDO.c
lp_crash.c
lp_etaPFI.c
lp_Hash.c
lp_lib.c
lp_matrix.c
lp_mipbb.c
lp_MPS.c
lp_presolve.c
lp_pricePSE.c
lp_report.c
lp_scale.c
lp_simplex.c
lp_SOS.c
lp_utils.c
lp_wlp.c

All header (.h) files from lpsolve must be accessible. Most compilers use the directive -Ipath with path the location to the header files. Note that the colamd directory also contains a header file that must be included.

If you also need the lp parser to read an lp model (read_lp, read_LP) then you must also include the files lp_rlp.c and yacc_read.c and define the symbol PARSER_LP. Most compilers use the directive -DPARSER_LP to do that. If you forget to define this symbol then the linker will give a link error saying that the symbols read_lp, read_LP are already defined. Also define the symbol YY_NEVER_INTERACTIVE (-DYY_NEVER_INTERACTIVE). This to disable the interactive mode of the lex parser and remove the dependency on isatty() routine which not available in all environments.

If you also need the CPLEX lp parser to read an lp model (read_lpt, read_LPT) and/or to write a CPLEX lp model, then you must also include the files lp_rlpt.c, lp_wlpt.c and yacc_read.c and define the symbol PARSER_CPLEX. Most compilers use the directive -DPARSER_CPLEX to do that. If you forget to define this symbol then the linker will give a link error saying that the symbols read_lpt, read_LPT, write_lpt, write_LPT are already defined. Also define the symbol YY_NEVER_INTERACTIVE (-DYY_NEVER_INTERACTIVE). This to disable the interactive mode of the lex parser and remove the dependency on isatty() routine which not available in all environments.

Note that lp_rlp.c, lp_rlp.h, lp_rlpt.c, lp_rlpt.h may give you some warnings when they are compiled. This is 'normal'. These files are not human-written, but generated from yacc/bison/lex tools from the corresponding .y and .l files. These tools don't seem to care much in generating code that is fully Ansi compliant and without warnings. Normally they can be ignored.

Note that there are more .c files in the lpsolve directory. You don't have to (even may not) include these in your project also. This because there files are either automatically included by the other source files or are needed for other functionality.

Statically link your application with the lpsolve code

With the Windows Microsoft compiler, the command could be:

cl -Ic:\lp_solve_5.0 /Zp8 -DWIN32 %src% -oMyExe.exe

With the Windows gnu compiler, the command could be:

gcc -Ic:\lp_solve_5.0 -DBFP_CALLMODEL=__stdcall %src% -oMyExe.exe

Under Unix/Linux, the command could be:

cc -I/lp_solve_5.0 $src -oMyExe.exe -lm -ldl

%src% / $src is an environment variable containing all source files. Note the /Zp8 option with the Windows c compiler. This is also important. It ensures 8-bit alignment. This is required when you make use of the BPF functionality (see Basis Factorization Packages) and the XLI functionality (see External Language Interfaces). It doesn't matter which calling convention is used. __cdecl or __stdcall or any other calling convention is ok, even if you make use of the BFP functionality. Note the -DBFP_CALLMODEL=__stdcall option with the non-Microsoft compiler. This is to define a macro for the BFP to make sure its routines are called via the __stdcall calling convention. This is required if you want to make use of the BFP functionality. If your compiler doesn't provide a way to specify the __stdcall calling convention, then you can drop this, but the BFP functionality will then probably not work (even crash). With the Microsoft compiler this option doesn't have to be specified because it is automatically set by the lpsolve header files via the WIN32 macro. Under Unix/Linux the -lm option must be added to link with the math library and the option -ldl is used to link with the shared library. Not all Unix systems have this functionality. In that case you can drop the -ldl option but then you have to add -DLoadInverseLib=0 -DLoadLanguageLib=0 in which case you will not be able to use the BFP functionality (see Basis Factorization Packages) and also not the XLI functionality (see External Language Interfaces).

The compiler commands to compile the package with also the lp (lpsolve and CPLEX) parser functionality:
With the Windows Microsoft compiler, the command could be:

cl -Ic:\lp_solve_5.0 /Zp8 -DWIN32 -DYY_NEVER_INTERACTIVE -DPARSER_CPLEX -DPARSER_LP %src% -oMyExe.exe

With the Windows gnu compiler, the command could be:

gcc -Ic:\lp_solve_5.0 -DBFP_CALLMODEL=__stdcall -DYY_NEVER_INTERACTIVE -DPARSER_CPLEX -DPARSER_LP %src% -oMyExe.exe

Under Unix/Linux, the command could be:

cc -I/lp_solve_5.0 -DYY_NEVER_INTERACTIVE -DPARSER_CPLEX -DPARSER_LP $src -oMyExe.exe -lm -ldl

And for Unix/Linux without the possibility to use the BFP and XLI functionality:

cc -I/lp_solve_5.0 -DYY_NEVER_INTERACTIVE -DPARSER_CPLEX -DPARSER_LP -DLoadInverseLib=0 -DLoadLanguageLib=0 $src -oMyExe.exe -lm

Note that I used here the command prompt commands to compile the sources. It is of course also possible to use the graphical interfaces with their project files to build it. The principle stays however the same.

In the lp_solve folder, there are also some batch/script files to build the lp_solve application. This may be a good start to begin. Note that lp_solve.c is here the application. It only contains this one source file. Or you could also look at the demo program in the demo directory. Here the application is demo.c

cvc6.bat Build the executable with the Microsoft Visual C/C++ version 6 and 7 (.NET) compiler. Note that some environment variables must be set to be able to use this batch file. These are set via a batch file provided by Microsoft: vcvars32.bat or via a special command prompt added by the Visual Studio setup.
cgcc.bat Build the executable with the GNU compiler (DOS/Windows)
ccc Build the executable with the Unix/Linux compiler. Enter sh ccc to execute the script.

Statically link your application with the lpsolve library

The lpsolve code is in a library file. Under Windows with the Microsoft compiler, this is in a .lib file. Under Unix and under Windows with the cygwin gcc compiler, this is in a .a file. Note for the Microsoft compiler the extension of the file. This is the same as for a dynamic library with implicit linking. This may be confusing. There is a big difference between a static library and an import library. It is unfortunate that Microsoft has used the same extension for both. A static library contains code and it is statically linked to the executable. An import library only contains symbol definitions so that the linker can resolve the symbols. An import library will thus be much smaller in size than a static library.
The static library file is provided with the lpsolve distribution and is called liblpsolve5.lib for the Microsoft compiler and liblpk5.a under Linux and with the cygwin gnu compiler under windows. It depends on the environment and the version how to link the static library with your code. For Linux and with the cygwin gnu compiler, just specify the .a file to the compile command line.:

cc pgr.c liblpk5.a

For the Microsoft visual C compiler it can be done as follows: Via the link.exe command this is done by just specifying the liblpsolve5.lib file at the command line. Via the .NET environment, this can be done via: Project, Properties, Linker, Input, Additional Dependencies. Optionally it is possible to also specify a link path via Project, Properties, Linker, General, Additional Library Directories. In Visual studio 6, this can be done via: Project, Settings, Link, Category General, Object/library modules. Optionally it is possible to also specify a link path via Project, Settings, Link, Category Input, Additional library path.
After this is done, the lpsolve functions can be called just like the lpsolve functions are linked to the program.

Dynamically link your application with the lpsolve library

lpsolve is separated from the application. So there are two separate compilations. One of the application and one of the lpsolve library. Most people will not compile the lpsolve library themselves since it is provided for several popular platforms. Therefore it is first explained how to access the lpsolve library in your application. This depends on the OS and the calling language. The most common are described here.

There are two ways of linking a dynamic library to the application: Implicit and Explicit linking. It depends on the programming language which way of linking is supported. Some support only one of the two, some can do both ways.

With Implicit Linking, the shared library file gets loaded into memory as soon as we execute the client program. If implicitly linked, the library is not removed from memory unless the application is terminated. However, if there are other applications in memory that are using the library, it is not removed from memory till the last of these applications is terminated.
If we want, we can defer the loading of the library till the time a call to the exported function in the library is not made. This is known as Explicit Linking. Explicit linking is more appropriate for interpreted languages such as Visual Basic, but it can also be used from C/C++ if we need to.

If Implicit Linking is used, a link (or import) library must be provided to the linker to resolve the symbols. In the code, the function calls are made as if all symbols are available.
If Explicit Linking is used, the library is explicitly loaded in memory via a special API call and the routines are also explicitly called via API calls. It should be clear that Explicit linking requires more coding than Implicit linking, but it allows you do load the library only when you need it and even decide at runtime from which library to call the routines.

Some may see Implicit linking as 'early binding' and Explicit linking as 'late binding'. Although it is not exactly the same, the analogy is true. Just like 'early binding', with Implicit linking, the symbols are resolved and checked at compile (actually link) time. There is strong type checking and less chance to pass wrong arguments. Just like 'late binding', with Explicit linking, the symbols are resolved and checked at runtime. The type checking is loose and there is chance that wrong parameters are passed to the function with possible disastrous results. But with the flexibility to dynamically load and call functions.
For Windows, there is a good article explaining all this: DLLs for Beginners

WINDOWS: Call the lpsolve dll from C/C++
Microsoft Visual C/C++ supports both Implicit and Explicit linking.
Implicit linking
In implicit linking, the linker matches the symbols of the library via a .lib file (the import library). Note the extension of the file. This is the same as for a static library. This may be confusing. There is a big difference between a static library and an import library. It is unfortunate that Microsoft has used the same extension for both. A static library contains code and it is statically linked to the executable. An import library only contains symbol definitions so that the linker can resolve the symbols. An import library will thus be much smaller in size than a static library. This file is provided with the lpsolve dll and is called lpsolve5.lib. It depends on the environment and the version how to do this. Via the link.exe command, this is done by just specifying the lpsolve5.lib file at the command line. Via the .NET environment, this can be done via: Project, Properties, Linker, Input, Additional Dependencies. Optionally it is possible to also specify a link path via Project, Properties, Linker, General, Additional Library Directories. In Visual studio 6, this can be done via: Project, Settings, Link, Category General, Object/library modules. Optionally it is possible to also specify a link path via Project, Settings, Link, Category Input, Additional library path.
After this is done, the lpsolve functions can be called just like the lpsolve functions are linked to the program.
Explicit linking
In explicit linking we don't use the .lib file. Instead we call the Win32 LoadLibrary( ) function, specifying the DLL's pathname as a parameter. The LoadLibrary( ) function returns an HINSTANCE parameter. This parameter is used in a call to the GetProcAddress( ) function to fetch the address of the function to be called. This address is a pointer to a function. Through this pointer the function is finally called. As can be seen in the following example, this requires some extra coding.

Example:
#include <stdio.h>

#include "lp_lib.h"

main()
{
  lprec *lp;
  HINSTANCE lpsolve;
  make_lp_func *_make_lp;
  delete_lp_func *_delete_lp;

  lpsolve = LoadLibrary("lpsolve5.dll");

  if (lpsolve == NULL) {
    printf("Unable to load lpsolve shared library\n");
    return(FALSE);
  }
  _make_lp = (make_lp_func *) GetProcAddress(lpsolve, "make_lp");
  _delete_lp = (delete_lp_func *) GetProcAddress(lpsolve, "delete_lp");

  lp = _make_lp(0,4);

  /* ... */

  _delete_lp(lp);

  FreeLibrary(lpsolve);
}
Note that the prototype definitions of the lpsolve functions (ex make_lp_func) are already defined in lp_lib.h. This same code also works with the Windows gnu gcc compiler. The only thing that must be done at compile time is defining the WIN32 macro. This will make sure that the calling convention will be __stdcall as required.
The C demo example demonstrates both implicit and explicit linking.
WINDOWS: Call the lpsolve dll from VB (also VBS Excel, Word, Access)

These environments support only Explicit linking. However it is easier than in C. Via a DECLARE statement, the API routines are declared and can immediately be called. The LoadLobrary/GetProcAddress API calls are not needed. To make things even easier, a class file is made to access the lpsolve library. It is called lpsolve5.cls. See the VB/Excel demos to see how it works.

WINDOWS: Call the lpsolve dll from VB.NET, C#

This is analog as for VB. These environments probably also allow to use implicit linking, but this is not investigated. There is also a class library made to call the lpsolve library. It is called lpsolve5.vb and lpsolve5.cs
See the demos for how it works.

Building the lpsolve shared library