c++ macos fortran dylib

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.