Mac Dynamic Library Craziness (May be Fortran Only)

冷暖自知 提交于 2019-12-08 10:50:37

问题


I have this fortran 90 file (will add the code to the bottom of the question) which I have compiled into a dynamic library on OS X Mavericks using the following command: gfortran -dynamiclib trianglepy.f90 -o libtriangle.dylib. This produces libtriangle.dylib which is stored on my desktop. I can than make a C++ file using this library(code attached at bottom). I than compile the code using g++ main.cpp -o main -std=c++11 -L ~/Desktop/ -ltriangle. This compiles the code perfectly. But when I run the produced executable, I get the following error:

dyld: Library not loaded: libtriangle.dylib
  Referenced from: /Users/zacharykraus/./main
  Reason: image not found
Trace/BPT trap: 5

When I run otool -L main I get

main:
    libtriangle.dylib (compatibility version 0.0.0, current version 0.0.0)
    /opt/local/lib/libgcc/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.20.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
    /opt/local/lib/libgcc/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)

If I try and export the correct path to LD_LIBRARY_PATH or DYLD_LIBRARY_PATH. I get the same error. The only way to get the executable main to run is to move the file main to the desktop. This runs successfully to produce:

the angles are 33.5496 61.5496 28 
the sides are 2.2 3.5 1.86885

Note: I dont think that triangle actually exists, but on to the actual question. Can some one please explain to me how I can get the executable to run from a different directory than the one libtriangle.dylib is in? Additinally, why does my executable only run when I move the executable to the same directory libtriangle.dylib is in?

The Fortran 90 code that produces libtriangle.dylib is:

!post all functions here
!double precision function area(side,angle)
!   double precision side(3),angle(3)
!end

double precision function sidelos(angle1,angle2,side2)
    double precision angle1, angle2, side2
    !law of sines to calculate the missing side
    sidelos=side2*sin(angle1*3.141593d0/180d0)/sin(angle2*3.141593d0/180d0)
end

double precision function anglelos(side1, side2, angle2)
    double precision side1, side2, angle2
    !law of sines to calculate the missing angle
    anglelos=asin(side1*sin(angle2*3.141593d0/180d0)/side2)*180d0/3.141593d0
end

double precision function sideloc(side1, side2, angle3)
    double precision side1, side2, angle3
    !law of cosines to calculate side 3
    sideloc=sqrt(side1**2 + side2**2 - 2d0*side1*side2*cos(angle3*3.141593d0/180d0))
end

double precision function angleloc(side1, side2, side3)
    implicit none
    double precision side1, side2, side3
    !law of cosines to calculate angle3
    angleloc=acos((side1**2 + side2**2 - side3**2) / 2d0/side1/side2)*180d0/3.141593d0
end

!post all subroutines here
subroutine asa(angle1, side3, angle2, angle, side)
    double precision angle(3), side(3), sidelos
    double precision angle1, side1, angle2
    integer i
    !f2py intent(out) angle
    !f2py intent(out) side
    angle(1) = angle1
    angle(2) = angle2
    side(3) = side3
    !calculate the third angle
    angle(3)=180-angle(1)-angle(2)
    do i=1,2
    !calculate the missing sides using law of sines
        side(i)=sidelos(angle(i),angle(3),side(3))
    end do
end

subroutine sas(side1, angle3, side2, angle, side)
    double precision angle(3), side(3), sideloc, anglelos
    double precision side1, angle3, side2
    integer i
    !f2py intent(out) angle
    !f2py intent(out) side
    side(1) = side1
    side(2) = side2
    angle(3) = angle3
    !calculate the missing side with law of cosines
    side(3)=sideloc(side(1),side(2),angle(3))
    do i=1,2
        !calculate the missing angles with the law of sines
        angle(i)=anglelos(side(i), side(3), angle(3))
    end do
end

subroutine sss(side1, side2, side3, angle, side)
    double precision angle(3), side(3), angleloc, anglelos
    double precision side1, side2, side3
    integer i
    !f2py intent(out) angle
    !f2py intent(out) side
    side(1) = side1
    side(2) = side2
    side(3) = side3
    !calculate the missing angle with law of cosines
    angle(3)=angleloc(side(1),side(2),side(3))
    do i=1,2
        !calculate the missing angles with the law of sines
        angle(i)=anglelos(side(i), side(3), angle(3))
    end do
end

subroutine aas(angle1, angle2, side1, angle, side)
    double precision angle(3), side(3), sidelos
    double precision angle1, angle2, side1
    integer i
    !f2py intent(out) angle
    !f2py intent(out) side
    angle(1) = angle1
    angle(2) = angle2
    side(1) = side1
    !calculate the third angle
    angle(3)=180-angle(1)-angle(2)
    do i=2,3
        !calculate the missing sides using law of sines
        side(i)=sidelos(angle(i),angle(1),side(1))
    end do
end

The C++ code that links to the dynamic library is:

extern "C" void sas_(double*, double*, double*, double*, double*);
#include <iostream>
using namespace std;
int main()
{
  double side1 = 2.2, side2= 3.5, angle3 = 28;
  double angle[3], side[3];
  sas_(&side1, &angle3, &side2, angle, side);
  cout << "the angles are ";
  for (double value : angle)
    cout << value <<" ";
  cout << endl;

  cout<<"the sides are ";
  for (double value : side)
    cout << value << " ";
  cout << endl;
  return 0;
}

回答1:


The answer has to do with how dynamic libraries work in mac os x. Dynamic libraries in os x always store a path in the library. When you compile the dynamic library the default path is the name of the library. When you link the dynamic library at compile time, the path in the library gets stored in the executable. Consequently, when you attempt to run main, the executable is looking for libtriangle.dylib in the current directory. This is why if you copy libtriangle.dylib to the current directory, the program runs correctly.

To fix the issue, add -install_name and the absolute path to the compilation. Than recompile the c++ file linking to libtriangle.dylib. After the recompile rerunning otool -L main gives:

main:
/Users/zacharykraus/Desktop/libtriangle.dylib (compatibility version 0.0.0, current version 0.0.0)
/opt/local/lib/libgcc/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.20.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
/opt/local/lib/libgcc/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)

Now the executable runs correctly without having to copy the dynamic library to the current path.



来源:https://stackoverflow.com/questions/27162276/mac-dynamic-library-craziness-may-be-fortran-only

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!