1 (edited by wwang328 2015-08-17 23:16:11)

Topic: how to include a .dll file in the project?

Hi Simply Fortran experts,

     I'm using the NLOPT interface for my project. The package contains a libnlopt-0.dll file, libnlopt-0.def file, and a nlopt.f file. As I'm new to using this type of library, would you suggest how to use them? Should I include them in the project pane, like the regular separate subroutine file?

Thanks a lot~

Re: how to include a .dll file in the project?

I believe you've downloaded the pre-compiled binaries for Windows if I'm not mistaken.  These files should work fine.  The file nlopt.f is actually just a list of parameters that you'd probably include in any routines needing it via:

INCLUDE 'nlopt.f'

You'll need to make sure the file is in the same directory as the rest of your source code.  You'll also need to compile and link against the DLL.  The simplest way to do this might be to actually add the DLL to your project.  From the Project menu, select "Add File(s)..." and select "libnlopt-0.dll."  When you build your program now, it should link against the DLL properly.  Again, make sure the DLL is in the same directory as the rest of your project.

As for the specifics of calling NLOPT, you'll need to look at their documentation.  If you do run into issues, please feel free to ask here!

Jeff Armstrong
Approximatrix, LLC

3 (edited by wwang328 2015-08-18 17:35:40)

Re: how to include a .dll file in the project?

Thank you for your reply, Jeff! I've followed what you suggests and carried out a test program, which is an example Fortram code copied from NLOPT website (let me name it test.f90). That means, the way using DLL file should be fine.

    With all files under the project in the same directory (test.f90, nlopt.f, libnlopt-0.dll, libnlopt-0.def), here is the error message that comes to me after I build it:

    Error: Unexpected end of file in '.\nlopt.f'
    Error(E42): Last command making (build\nlopt.o) returned a bad status
    Error(E02): Make execution terminated

Is it because nlopt.f is written in Fortran 77? Shouldn't .f file still able to be compiled by SF? Here's how nlopt.f is written:

   

       integer NLOPT_GN_DIRECT
      parameter (NLOPT_GN_DIRECT=0)
      integer NLOPT_GN_DIRECT_L
      parameter (NLOPT_GN_DIRECT_L=1)
      integer NLOPT_GN_DIRECT_L_RAND
      parameter (NLOPT_GN_DIRECT_L_RAND=2)
      integer NLOPT_GN_DIRECT_NOSCAL
      parameter (NLOPT_GN_DIRECT_NOSCAL=3)
      integer NLOPT_GN_DIRECT_L_NOSCAL
      parameter (NLOPT_GN_DIRECT_L_NOSCAL=4)
      integer NLOPT_GN_DIRECT_L_RAND_NOSCAL
      parameter (NLOPT_GN_DIRECT_L_RAND_NOSCAL=5)
      integer NLOPT_GN_ORIG_DIRECT
      parameter (NLOPT_GN_ORIG_DIRECT=6)
      integer NLOPT_GN_ORIG_DIRECT_L
      parameter (NLOPT_GN_ORIG_DIRECT_L=7)
      integer NLOPT_GD_STOGO
      parameter (NLOPT_GD_STOGO=8)
      integer NLOPT_GD_STOGO_RAND
      parameter (NLOPT_GD_STOGO_RAND=9)
      integer NLOPT_LD_LBFGS_NOCEDAL
      parameter (NLOPT_LD_LBFGS_NOCEDAL=10)
      integer NLOPT_LD_LBFGS
      parameter (NLOPT_LD_LBFGS=11)
      integer NLOPT_LN_PRAXIS
      parameter (NLOPT_LN_PRAXIS=12)
      integer NLOPT_LD_VAR1
      parameter (NLOPT_LD_VAR1=13)
      integer NLOPT_LD_VAR2
      parameter (NLOPT_LD_VAR2=14)
      integer NLOPT_LD_TNEWTON
      parameter (NLOPT_LD_TNEWTON=15)
      integer NLOPT_LD_TNEWTON_RESTART
      parameter (NLOPT_LD_TNEWTON_RESTART=16)
      integer NLOPT_LD_TNEWTON_PRECOND
      parameter (NLOPT_LD_TNEWTON_PRECOND=17)
      integer NLOPT_LD_TNEWTON_PRECOND_RESTART
      parameter (NLOPT_LD_TNEWTON_PRECOND_RESTART=18)
      integer NLOPT_GN_CRS2_LM
      parameter (NLOPT_GN_CRS2_LM=19)
      integer NLOPT_GN_MLSL
      parameter (NLOPT_GN_MLSL=20)
      integer NLOPT_GD_MLSL
      parameter (NLOPT_GD_MLSL=21)
      integer NLOPT_GN_MLSL_LDS
      parameter (NLOPT_GN_MLSL_LDS=22)
      integer NLOPT_GD_MLSL_LDS
      parameter (NLOPT_GD_MLSL_LDS=23)
      integer NLOPT_LD_MMA
      parameter (NLOPT_LD_MMA=24)
      integer NLOPT_LN_COBYLA
      parameter (NLOPT_LN_COBYLA=25)
      integer NLOPT_LN_NEWUOA
      parameter (NLOPT_LN_NEWUOA=26)
      integer NLOPT_LN_NEWUOA_BOUND
      parameter (NLOPT_LN_NEWUOA_BOUND=27)
      integer NLOPT_LN_NELDERMEAD
      parameter (NLOPT_LN_NELDERMEAD=28)
      integer NLOPT_LN_SBPLX
      parameter (NLOPT_LN_SBPLX=29)
      integer NLOPT_LN_AUGLAG
      parameter (NLOPT_LN_AUGLAG=30)
      integer NLOPT_LD_AUGLAG
      parameter (NLOPT_LD_AUGLAG=31)
      integer NLOPT_LN_AUGLAG_EQ
      parameter (NLOPT_LN_AUGLAG_EQ=32)
      integer NLOPT_LD_AUGLAG_EQ
      parameter (NLOPT_LD_AUGLAG_EQ=33)
      integer NLOPT_LN_BOBYQA
      parameter (NLOPT_LN_BOBYQA=34)
      integer NLOPT_GN_ISRES
      parameter (NLOPT_GN_ISRES=35)
      integer NLOPT_AUGLAG
      parameter (NLOPT_AUGLAG=36)
      integer NLOPT_AUGLAG_EQ
      parameter (NLOPT_AUGLAG_EQ=37)
      integer NLOPT_G_MLSL
      parameter (NLOPT_G_MLSL=38)
      integer NLOPT_G_MLSL_LDS
      parameter (NLOPT_G_MLSL_LDS=39)
      integer NLOPT_LD_SLSQP
      parameter (NLOPT_LD_SLSQP=40)
      integer NLOPT_LD_CCSAQ
      parameter (NLOPT_LD_CCSAQ=41)
      integer NLOPT_GN_ESCH
      parameter (NLOPT_GN_ESCH=42)
      integer NLOPT_FAILURE
      parameter (NLOPT_FAILURE=-1)
      integer NLOPT_INVALID_ARGS
      parameter (NLOPT_INVALID_ARGS=-2)
      integer NLOPT_OUT_OF_MEMORY
      parameter (NLOPT_OUT_OF_MEMORY=-3)
      integer NLOPT_ROUNDOFF_LIMITED
      parameter (NLOPT_ROUNDOFF_LIMITED=-4)
      integer NLOPT_FORCED_STOP
      parameter (NLOPT_FORCED_STOP=-5)
      integer NLOPT_SUCCESS
      parameter (NLOPT_SUCCESS=1)
      integer NLOPT_STOPVAL_REACHED
      parameter (NLOPT_STOPVAL_REACHED=2)
      integer NLOPT_FTOL_REACHED
      parameter (NLOPT_FTOL_REACHED=3)
      integer NLOPT_XTOL_REACHED
      parameter (NLOPT_XTOL_REACHED=4)
      integer NLOPT_MAXEVAL_REACHED
      parameter (NLOPT_MAXEVAL_REACHED=5)
      integer NLOPT_MAXTIME_REACHED
      parameter (NLOPT_MAXTIME_REACHED=6)

Sorry for the long post and I hope I made my question clear. Thanks!

Re: how to include a .dll file in the project?

The file nlopt.f shouldn't be compiled separately.  As you may have noticed, it contains only parameter definitions.  When the compiler encounters this file, it gets confused since it doesn't actually do anything other than declare variables.

Assuming your test program test.f90 is already INCLUDE-ing the file nlopt.f, you need to tell Simply Fortran that it shouldn't be compiled separately.  In the Project Outline panel, right-click on nlopt.f and select "Disable File" from the popup menu.  Simply Fortran will now no longer attempt to compile nlopt.f on its own.

Jeff Armstrong
Approximatrix, LLC

5 (edited by wwang328 2015-08-19 19:32:16)

Re: how to include a .dll file in the project?

That makes sense. Thanks, Jeff!

       I later found out the example in NLopt website is written in fortram 77 http://ab-initio.mit.edu/wiki/index.php/NLopt_Tutorial.
But changing the extension of test.f90 into test.f does not work.

       The following question might be a bit off of the original theme and may sound stupid, since it's likely to be caused by my infamilarity with Fortran 77 language.

        So here is the test. f file, with 6 indents for every line:
   

      program main
      external myfunc, myconstraint
      double precision lb(2)
      integer*8 opt
      double precision d1(2), d2(2)
      double precision x(2), minf
      integer ires
      include 'nlopt.f'
      
      opt=0
      call nlo_create(opt, NLOPT_LD_MMA, 2)
      call nlo_get_lower_bounds(ires, opt, lb)
      lb(2) = 0.0
      call nlo_set_lower_bounds(ires, opt, lb)
      call nlo_set_min_objective(ires, opt, myfunc, 0)
     
      d1(1) = 2.
      d1(2) = 0.
      call nlo_add_inequality_constraint(ires, opt, myconstraint, 
      $ d1, 1.D-8)
      d2(1) = -1.
      d2(2) = 1.
      call nlo_add_inequality_constraint(ires, opt, myconstraint, 
      $ d2, 1.D-8)
     
      call nlo_set_xtol_rel(ires, opt, 1.D-4)
     
      x(1) = 1.234
      x(2) = 5.678
      call nlo_optimize(ires, opt, x, minf)
      if (ires.lt.0) then
        write(*,*) 'nlopt failed!'
      else
        write(*,*) 'found min at ', x(1), x(2)
        write(*,*) 'min val = ', minf
      endif
     
      call nlo_destroy(opt)
     
      end 
     
      subroutine myfunc(val, n, x, grad, need_gradient, f_data)
      double precision val, x(n), grad(n)
      integer n, need_gradient
      if (need_gradient.ne.0) then
         grad(1) = 0.0
         grad(2) = 0.5 / dsqrt(x(2))
      endif
      val = dsqrt(x(2))
      end 
     
      subroutine myconstraint(val, n, x, grad, need_gradient, d)
      integer need_gradient
      double precision val, x(n), grad(n), d(2), a, b
      a = d(1)
      b = d(2)
      if (need_gradient.ne.0) then
        grad(1) = 3. * a * (a*x(1) + b)**2
        grad(2) = -1.0
      endif
      val = (a*x(1) + b)**3 - x(2)
      end               

      I compile it with libnlopt-0.def, libnlopt-0.dll, nlopt.f (disabled) and test.f under the project and receives such info:

          "C:\Program Files (x86)\Simply Fortran\mingw-w64\bin\gfortran.exe" -c -o "build\test.o" -g -m32   -Jmodules ".\test.f"
.\test.f:19.72:

      call nlo_add_inequality_constraint(ires, opt, myconstraint, d1, 1.
                                                                        1
Error: Syntax error in argument list at (1)
.\test.f:22.72:

      call nlo_add_inequality_constraint(ires, opt, myconstraint, d2, 1.
                                                                        1
Error: Syntax error in argument list at (1)
Error(E42): Last command making (build\test.o) returned a bad status
Error(E02): Make execution terminated

       This seems weird as (i) it's a copied code from website (ii) it matches the format requirement in the reference
 

 call nlo_add_inequality_constraint(ires, opt, fc, fc_data, tol) 

I doubt there's some stupid error there, and I would sincerely appreciate if you can have a look at that!

6 (edited by wwang328 2015-08-20 00:41:44)

Re: how to include a .dll file in the project?

OK. Stackoverflow helps me to identify the misplaced $ sign in calling nlo_add_inequality_constraint and it should be in the 6th indention before the rest of codes.

     Fixing that, the test.f file can be built. But I got the following error message

   

 c:/program files (x86)/simply fortran/mingw-w64/bin/../lib/gcc/x86_64-w64-mingw32/4.8.1/../../../../x86_64-w64-mingw32/lib/../lib32\libmingw32.a(lib32_libmingw32_a-CRT_fp10.o):CRT_fp10.c:(.text+0x0): multiple definition of `fpreset'
.\libnlopt-0.dll:/build/mingw-w64-RGpMuZ/mingw-w64-2.0.3/build/x86_64-w64-mingw32/all/mingw-w64-crt/../../../../mingw-w64-crt/crt/CRT_fp10.c:12: first defined here
c:/program files (x86)/simply fortran/mingw-w64/bin/../lib/gcc/x86_64-w64-mingw32/4.8.1/../../../../x86_64-w64-mingw32/bin/ld.exe: i386:x86-64 architecture of input file `.\libnlopt-0.dll' is incompatible with i386 output
build\test.o: In function `MAIN__':
D:\Dropbox\fortran\nlopt-2.4.2-dll64/./test.f:11: undefined reference to `nlo_create_'
D:\Dropbox\fortran\nlopt-2.4.2-dll64/./test.f:12: undefined reference to `nlo_get_lower_bounds_'
D:\Dropbox\fortran\nlopt-2.4.2-dll64/./test.f:14: undefined reference to `nlo_set_lower_bounds_'
D:\Dropbox\fortran\nlopt-2.4.2-dll64/./test.f:15: undefined reference to `nlo_set_min_objective_'
D:\Dropbox\fortran\nlopt-2.4.2-dll64/./test.f:20: undefined reference to `nlo_add_inequality_constraint_'
D:\Dropbox\fortran\nlopt-2.4.2-dll64/./test.f:24: undefined reference to `nlo_add_inequality_constraint_'
D:\Dropbox\fortran\nlopt-2.4.2-dll64/./test.f:26: undefined reference to `nlo_set_xtol_rel_'
D:\Dropbox\fortran\nlopt-2.4.2-dll64/./test.f:30: undefined reference to `nlo_optimize_'
D:\Dropbox\fortran\nlopt-2.4.2-dll64/./test.f:38: undefined reference to `nlo_destroy_'
collect2.exe: error: ld returned 1 exit status
Error(E42): Last command making (Project.exe) returned a bad status
Error(E02): Make execution terminated 

     According to one post http://permalink.gmane.org/gmane.scienc … eneral/662 here, it seems any Fortran function fun should have a C name fun_. roll

     The post is not illustrative though, at least not to beginners like me.... Would you suggest how to fix that? Thanks again!

Re: how to include a .dll file in the project?

In this case, the linker is failing because you've compiled your Fortran code for a 32-bit target, but you're trying to use it with a 64-bit DLL.  If you open Project Options and switch to 64-bit architecture (remember to save your project afterwards!), you should be able to compile and link properly.

The missing functions you're seeing are only because you're using a 64-bit DLL with code you compiled as 32-bit.  Once you fix that error, you might run into another issue with the trailing underscore, but perhaps not.  The link you've provided is for Intel's Fortran compiler, and I don't know how it treats C vs. Fortran function decorations.  It's best to ignore the link you've provided for now.

Jeff Armstrong
Approximatrix, LLC

Re: how to include a .dll file in the project?

Hi Jeff, Thank you so much for your fast response!:) After stucking there for a day or two, the program is finally running and giving results! smile  Now I can continue to work out the real problem now!~

Re: how to include a .dll file in the project?

That's great to hear!  If you encounter any other problems or have some further suggestions, please do post here.

Jeff Armstrong
Approximatrix, LLC

Re: how to include a .dll file in the project?

Hi Jeff,

    It seems that NLopt is really working now in my project! smile Thanks again!

    Now I have another question about profiler. I think it's probably a better idea starting a new thread for future search:)