c++ - Locura de Mac Dynamic Library(puede ser Fortran solamente)
macos dylib (1)
Tengo este archivo fortran 90 (agregará el código al final de la pregunta) que he compilado en una biblioteca dinámica en OS X Mavericks usando el siguiente comando: gfortran -dynamiclib trianglepy.f90 -o libtriangle.dylib
. Esto produce libtriangle.dylib que está almacenado en mi escritorio. Puedo hacer un archivo C ++ utilizando esta biblioteca (código adjunto en la parte inferior). Yo compilo el código usando g++ main.cpp -o main -std=c++11 -L ~/Desktop/ -ltriangle
. Esto compila el código perfectamente. Pero cuando ejecuto el ejecutable producido, aparece el siguiente error:
dyld: Library not loaded: libtriangle.dylib
Referenced from: /Users/zacharykraus/./main
Reason: image not found
Trace/BPT trap: 5
Cuando corro el otool -L main
me sale
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)
Si intento exportar la ruta correcta a LD_LIBRARY_PATH o DYLD_LIBRARY_PATH. Me sale el mismo error. La única forma de ejecutar el ejecutable principal es mover el archivo principal al escritorio. Esto se ejecuta con éxito para producir:
the angles are 33.5496 61.5496 28
the sides are 2.2 3.5 1.86885
Nota: no creo que ese triángulo exista en realidad, sino que siga la pregunta real. ¿Puede alguien explicarme cómo puedo hacer que el ejecutable se ejecute desde un directorio diferente al que está en el que está libtriangle.dylib? Además, ¿por qué mi ejecutable solo se ejecuta cuando muevo el ejecutable al mismo directorio en el que está libtriangle.dylib?
El código de Fortran 90 que produce libtriangle.dylib es:
!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
El código de C ++ que se vincula a la biblioteca dinámica es:
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;
}
La respuesta tiene que ver con cómo funcionan las bibliotecas dinámicas en mac os x. Las bibliotecas dinámicas en os x siempre almacenan una ruta en la biblioteca. Cuando compila la biblioteca dinámica, la ruta predeterminada es el nombre de la biblioteca. Cuando vincula la biblioteca dinámica en tiempo de compilación, la ruta en la biblioteca se almacena en el archivo ejecutable. En consecuencia, cuando intenta ejecutar main, el ejecutable busca libtriangle.dylib en el directorio actual. Esta es la razón por la cual si copia libtriangle.dylib al directorio actual, el programa se ejecuta correctamente.
Para solucionar el problema, agregue -install_name y la ruta absoluta a la compilación. Que recompilar el archivo c ++ que se vincula a libtriangle.dylib. Después de volver a compilar la otool -L main
obtiene:
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)
Ahora el ejecutable se ejecuta correctamente sin tener que copiar la biblioteca dinámica a la ruta actual.