У меня есть этот файл fortran 90 (я добавлю код в конец вопроса), который я скомпилировал в динамическую библиотеку на OS X Mavericks с помощью следующей команды: gfortran -dynamiclib trianglepy.f90 -o libtriangle.dylib
, Это создает libtriangle.dylib, который хранится на моем рабочем столе. Я могу сделать файл C ++, используя эту библиотеку (код прикреплен внизу). Я, чем скомпилировать код, используя g++ main.cpp -o main -std=c++11 -L ~/Desktop/ -ltriangle
, Это прекрасно компилирует код. Но когда я запускаю созданный исполняемый файл, я получаю следующую ошибку:
dyld: Library not loaded: libtriangle.dylib
Referenced from: /Users/zacharykraus/./main
Reason: image not found
Trace/BPT trap: 5
Когда я бегу otool -L main
я получил
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)
Если я попытаюсь экспортировать правильный путь в LD_LIBRARY_PATH или DYLD_LIBRARY_PATH. Я получаю ту же ошибку. Единственный способ запустить исполняемый файл main — переместить файл main на рабочий стол. Это успешно работает, чтобы произвести:
the angles are 33.5496 61.5496 28
the sides are 2.2 3.5 1.86885
Примечание: я не думаю, что этот треугольник действительно существует, но по фактическому вопросу.
Может кто-нибудь объяснить мне, как заставить исполняемый файл работать из другого каталога, чем тот, в котором находится libtriangle.dylib? Кроме того, почему мой исполняемый файл запускается только тогда, когда я перемещаю исполняемый файл в тот же каталог, в котором находится libtriangle.dylib?
Код Fortran 90, который производит libtriangle.dylib:
!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
Код C ++, который ссылается на динамическую библиотеку:
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;
}
Ответ связан с тем, как динамические библиотеки работают в Mac OS X. Динамические библиотеки в OS X всегда хранят путь в библиотеке. Когда вы компилируете динамическую библиотеку, путь по умолчанию — это имя библиотеки. Когда вы связываете динамическую библиотеку во время компиляции, путь в библиотеке сохраняется в исполняемом файле. Следовательно, когда вы пытаетесь запустить main, исполняемый файл ищет libtriangle.dylib в текущем каталоге. Вот почему, если вы скопируете libtriangle.dylib в текущий каталог, программа будет работать правильно.
Чтобы решить эту проблему, добавьте -install_name и абсолютный путь к компиляции. Затем перекомпилируйте файл c ++, ссылающийся на libtriangle.dylib. После перекомпиляции перезапуска otool -L main
дает:
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)
Теперь исполняемый файл работает правильно, без необходимости копировать динамическую библиотеку в текущий путь.