Lucas Martins de Souza Ответов: 3

Преобразование кода FORTRAN в C#


Привет ребята,

Я постоянно ищу что-то здесь, и почти все время нахожу то, что мне нужно.
Но я знаю, что мне нужно что-то более конкретное, и я не могу найти его ни в google, ни здесь.

У меня есть большой код на Фортране 77. С кучей подпрограмм и функций.
И я хочу повторно использовать этот код в этом новом приложении C#, которое я программирую, я хотел бы сделать эти функции и подпрограммы доступными в классе или что-то в этом роде.

Как я уже видел в интернете и швах, правильный способ-это создание DLL с кодом и использование его в Visual Studio.

Но я не могу этого сделать, я уже пробовал Lahey-Fujitsu Fortran, WATCOM и Silverfrost.

С помощью Lahey и WATCOM я могу сделать dll, но VS2008 не примет ее в качестве ссылки.
В нем говорится: "пожалуйста, убедитесь, что файл доступен и что это допустимая сборка или COM-компонент"

С silverfrost я могу ссылаться на DLL, но.. когда я запускаю код ( во время выполнения), он говорит, что VS не может найти никаких экспортов в DLL.

Я понятия не имею, что делать дальше. Может ли кто-нибудь разместить здесь пример или показать мне, как это сделать, пожалуйста?

Я был бы вам очень признателен. :-)


Спасибо,

Лукас

Sergey Alexandrovich Kryukov

Даже если бы вы могли сделать что-то подобное, это нельзя было бы назвать "обращением" - все слишком по-другому...
--СА

3 Ответов

Рейтинг:
27

Lucas Martins de Souza

Привет вам, ребята! :)

После безостановочных исследований я просто привел простой пример. И теперь я думаю, что могу расширить это до моего проекта дыры!

Способ пойти-это использовать OPEN WATCOM FORTRAN ( whitch свободен, загрузите его здесь: http://www.openwatcom.org/index.php/Main_Page[^] и я использовал VS2010, но я думаю, что это не имеет значения.

Я покажу вам, ребята, как это делается!

Вступление:

Я собираюсь создать подпрограмму в FORTRAN77, которая принимает 3 двойника в качестве параметров 1 в качестве значения, а другие 2 в качестве ссылок, я буду называть ее DON.

Дону( double1, double2, двойной 3 )

Эта подпрограмма будет вызвана из кода C# и ее супоссирование будет возвращать (double1+1) и ( double1+2 ).

Итак ... вот код Фортрана:

*$ПРАГМА ОКС дон "дон" экспорт Парм(значение*8, справка, справка)


ПОДПРОГРАММА ДОНУ(ДАА,ДВВ,ПКС)
REAL*8, DAA,DBB,DCC
DBB=DAA+1
DCC=DBB+1
ВЕРНУТЬ
КОНЕЦ


* Важная информация о коде-это первая строка! Тот, который начинается с *$pragma ..да! эта линия! Он используется компилятором OPEN WATCOM, является директивой, используемой для указания того, что DLL получает двойное значение as, а также другие 2 ссылки

* Не забывайте, что ваш код FORTRAN должен иметь правильный отступ. ( правильное количество пробелов, я думаю, равно 6 )

Затем создайте проект DLL в WATCOMP и добавьте этот код в качестве исходного кода. Использовать по умолчанию и параметры.

Постройте, и вы создадите DLL, поместите ее в ту же папку, что и ваш .exe (не пытайтесь добавить ее в свой проект с помощью "добавить ссылку" из ссылок, потому что это не сработает.)

Теперь код C# :

Я опубликую свой код класса дырки:

public unsafe class Program
    {

        [DllImport("Lks.dll",
            CharSet = CharSet.Auto,
            CallingConvention = CallingConvention.StdCall)]
        public static extern void DON(
            [MarshalAs(UnmanagedType.R8)] double DAA,
            [MarshalAs(UnmanagedType.R8)] ref double DBB,
            [MarshalAs(UnmanagedType.R8)] ref double DCC
            );

        static unsafe void Main(string[] args)
        {
            //double TIME = 100.0;
            double DAA = 5.5;
            double DBB = 7;
            double DCC = 9;
            //START( ENERIN, VAL1);
            DON(DAA,ref DBB, ref DCC);

            Console.Write("val1 = " + DAA);
            Console.Write("val2 = " + DCC);
            Debug.WriteLine("VAR = " + DBB.ToString());
            Console.Write("Press any key to exit");
            Console.ReadKey(false);
        }
    }


Это будет так же, как и для Systme.Время выполнения.InteropServices, просто добавьте это в верхней части.

Запустите код и вы получите:

val1 = 5,5val2 = 7,5 нажмите любую клавишу для выхода

Это означает, что все прошло хорошо DAA = 5,5, а DCC теперь равен 7,5.

Спасибо, ребята! И не сдавайся.

Лукас


Рейтинг:
2

alireza moghimi

PROGRAM VLM
use MSIMSL
IMPLICIT NONE
REAL*8,allocatable   ::  XB(:),A(:,:),BL(:),SOLV(:),PHI(:),PHIW(:),PHIOLD(:)
REAL*8,allocatable   ::  CF(:)
INTEGER               ::  I,J,NW,NB,IT
REAL*8      ::  UINF,ALPHA,PI,DT,CL,AINF,DX,TIME,T,T0,MACH,SUM1

   
   OPEN (6,FILE="CLT.DAT")
   OPEN (4,FILE="CIRCUL.DAT")

   PI = Dacos(-1.0D0)
   
   ALPHA = 2.0D0 * PI / 180.0d0 
   DX   = 0.01D0 
   MACH = 0.000001D0
!   AINF = 300.0d0
!   UINF = MACH * AINF
   UINF = 1.0D0
   AINF = UINF / MACH
   DT = 0.01d0  !1.5D0 / ( 1.0d0/MACH+1.0d0)
   TIME = 10.0D0
   NW = TIME / DT
   NB = 1.0D0 / DX + 1
   ALLOCATE(XB(NB),A(NB,NB),BL(NB),SOLV(NB),PHI(NB),PHIOLD(NB),PHIW(NW),CF(NB-1))
   
   CALL READMESH (NB,DX,XB)
  
   PHI = 0.0D0 ; PHIW = 0.0D0 ;  PHIOLD =0.0D0

SUM1 = 0.0D0 
 
DO IT = 1 , TIME/DT
     T= IT * DT
     T0 = 0.0D0
     PHIW(IT) = PHI(NB)
	 PHIOLD = PHI

     CALL COEFF_MATRIX (DT,T,T0,UINF,AINF,NB,XB,A)
	 CALL RHS_VECTOR (NB,NW,IT,SUM1,XB,PHIW,ALPHA,UINF,AINF,DT,T,T0,BL)

     CALL DLSARG (NB, A, NB, BL, 1, SOLV)
     
	 DO I = 1 , NB
       PHI(I) = SOLV(I)
	 END DO
	 
	 CALL PRESS(DX,DT,UINF,NB,PHI,PHIOLD,CF,CL)
     
	 WRITE(6,*)IT*DT , CL/(2.0d0*PI*alpha)
     WRITE(*,*)IT*DT , CL/(2.0d0*PI*alpha)
    
END DO  ! TIME
   
     DO I = NB-1 , 1 ,-1
            WRITE(4,102)XB(I) , PHI(I)
	 END DO

102 Format (1x,10(1x,f14.5))
STOP
END
!-----------------------------------------------------------------------------------------
!-------------------------------- SUBROUTINES --------------------------------------------
!-----------------------------------------------------------------------------------------
SUBROUTINE PRESS(DX,DT,UINF,NB,PHI,PHIOLD,CF,CL)
   Implicit NONE
   INTEGER,INTENT(IN)  :: NB
   REAL*8,INTENT(IN)   :: PHI(NB),PHIOLD(NB),DT,UINF,DX
   REAL*8,INTENT(OUT)  :: CF(NB-1),CL
   REAL*8              :: SUM
   INTEGER             :: I,J
   CF = 0.0D0
   DO I = 1 , NB-1
	 SUM = 0.0D0
	 DO J = 1 , I
	    SUM = SUM + (PHI(J) - PHIOLD(J) )
     END DO 
      CF(I) = 1.0D0 * UINF *  PHI(I) + 1.0D0 / DT  * SUM * DX 
   END DO

   CL = 0.0D0
   DO I = 1 , NB-1
     CL = CL + CF(i) / (0.5 * 1.0D0 * UINF**2 * 1.0D0)
   END DO
END SUBROUTINE PRESS 

SUBROUTINE RHS_VECTOR (NB,NW,IT,SUM1,XB,PHIW,ALPHA,UINF,AINF,DT,T,T0,BL)
   Implicit NONE
   INTEGER,INTENT(IN) :: NB,NW,IT
   REAL*8,INTENT(IN)  :: XB(NB),PHIW(NW),ALPHA,UINF,AINF,DT,T,T0
   REAL*8,INTENT(INOUT) :: SUM1
   REAL*8,INTENT(OUT) :: BL(NB)
   REAL*8             :: X,PI,PI2,DX,DTL,SUM2
   INTEGER::I,J,K
   PI = Dacos(-1.0D0)
   PI2 = 2.0D0*PI
   

     SUM1 = SUM1 + PHIW(IT)  
     BL(NB) = -SUM1    

     Do I = 1 , NB-1            ! loop over collocation points , X0 : Collocation Point
   	   X = ( 3.0D0*XB(I) + 1.0D0*XB(I+1) ) / 4.0D0 
	   SUM2 = 0.0D0
	   DO J = 1 , IT
         DTL = (IT+2-J) * DT  	     
	     DX = X - (1.0D0 + UINF * DTL)  
!	 if ((AINF * DTL)**2 - DX**2 .lt. 0.0d0) then 
!	  write(*,*)'pause3'
!	  write(*,*)t ,i ,j , x ,  1.0D0 + UINF * DT 
!	  end if
         SUM2 = SUM2 - PHIW(J) / (PI2 * AINF * DTL * DX)  * DSQRT ( (AINF * DTL)**2 - DX**2)
!	     SUM2 = SUM2 - PHIW(J) / (PI2 * DX) 
       END DO 
     BL(I) = -UINF * alpha - SUM2
	 END DO
END SUBROUTINE RHS_VECTOR
						
SUBROUTINE COEFF_MATRIX (DT,T,T0,UINF,AINF,NB,XB,A)
   Implicit NONE
   INTEGER,INTENT(IN) :: NB
   REAL*8,INTENT(IN)  :: XB(NB),DT,T,T0,UINF,AINF
   REAL*8,INTENT(OUT) :: A(NB,NB)
   REAL*8             :: X,X0,G,PI,PI2,DX,DTL
   INTEGER::I,J,K
   PI = Dacos(-1.0D0)
   PI2 = 2.0D0*PI
   DTL = T - T
   A=0.0D0
   
   Do I=1,NB-1            ! loop over collocation points , X : Collocation Point
   	  X = ( 3.0D0*XB(I) + 1.0D0*XB(I+1) ) / 4.0D0
	  Do J=1,NB-1         ! loop over ELEMENTS OF AIRFOIL (B)
    	 X0 = ( 1.0D0*XB(J) + 3.0D0*XB(J+1)) / 4.0D0
		 DX = X - X0
!	  if ((AINF*DT)**2 - (DX-UINF*DT)**2 .lt. 0.0d0) then 
!	  write(*,*)'pause1'
!	  write(*,*) i , j , x ,  DX , (AINF*DT)**2 - (DX-UINF*DT)**2
!	  end if
         G  =  -1.0D0 / (PI2 * AINF *DX * DT)  * DSQRT ((AINF*DT)**2 - (DX-UINF*DT)**2) 
   		 A(I,J) = G
      END DO  ! J
  
      DX = X - ( 1.0D0 + UINF * DT )
!	  if ((AINF * DT)**2 - DX**2 .lt. 0.0d0) then 
!	  write(*,*)'pause2'
!	  write(*,*)t ,i , x ,  (AINF * DT)**2 , DX**2
!	  end if
      G  =  -1.0D0/(PI2 * AINF * DT * DX) * DSQRT ((AINF*DT)**2 - DX **2)
!      G  =  -1.0D0/(PI2 * DX) 
 	  A(I,NB) = G
   END DO     ! I
   A(NB,:) = 1.0D0
END SUBROUTINE COEFF_MATRIX


SUBROUTINE READMESH (NB,DX,XB)
   Implicit NONE
   INTEGER,INTENT(IN):: NB
   REAL*8 , INTENT (IN):: DX
   REAL*8 , INTENT (OUT):: XB(NB)
   INTEGER::I,J
   DO I = 1 , NB
	 XB(I) = 1.0D0 - (I-1)*DX
   END DO	 	 
END SUBROUTINE READMESH


CHill60

Должно ли это быть решением этого годичного вопроса?

Рейтинг:
0

Sergey Alexandrovich Kryukov

Прислушайтесь к хорошему дружескому совету: не тратьте время на поиск способа автоматического "перевода" кода. Фортран-это просто археология (неважно, что скажут люди, использующие его). Лучше хорошенько выучиться .NET и C#, сядьте и напишите код на C#, используя код FORTRAN только в качестве ссылки.

—СА


Lucas Martins de Souza

Я просто хочу сделать что-то вроде того, что сделал этот парень.

http://www.codeproject.com/Articles/1696/Fortran-for-Microsoft-NET

Я думаю, что это возможно и сэкономит мне много времени.

Sergey Alexandrovich Kryukov

Ну, а что мешает вам воспользоваться результатами этого парня? Интересно, но я бы не стал переоценивать его полезность...
--СА

Lucas Martins de Souza

Я не мог заставить его работать. Все,что он упомянул в своей статье, устарело, я не мог найти LaheyFortranPreview1, который, как мне кажется, является ключевым моментом для всей "магии".
Я искал другие решения, подобные этому здесь:
http://coding.derkeiler.com/Archive/Fortran/comp.lang.fortran/2007-08/msg00015.html
Это использует OpenWatcom, но не может заставить его работать ни то, ни другое.
Самое близкое, что я получил, было использование SilverFrost ( http://www.silverfrost.com/52/ftn95/ftn95_express.aspx) чтобы сделать DLL и попробовать простую программу, подобную этой ( http://stackoverflow.com/questions/10317691/making-fortran-dll-and-calling-it-from-c-sharp)

Но VS2008 говорит, что моя DLL не имеет экспорта. Это похоже на работу для хардкорного программиста, который много знает о windows DLL и Fortran, но не уверен, что у меня получится.

Sergey Alexandrovich Kryukov

Честно говоря, последуйте моему совету. Это миф о том, что повторное использование старого кода-это хорошо. Когда вы пишете код самостоятельно и используете устаревший только в качестве ссылки, вы не воспроизводите старые ошибки; а новые вы можете отлаживать легче, потому что ваш опыт свеж... использование автоматического "перевода" может быть просто разочарованием и пустой тратой времени.

Если вы чувствуете себя убежденным, пожалуйста, укажите это, приняв мой ответ формально (зеленая кнопка) - спасибо. :-)
--СА

Lucas Martins de Souza

У меня есть еще несколько дней, чтобы продолжать пробовать новые вещи, и если я найду что-то новое и интересное, я опубликую здесь, чтобы помочь другим ;-) В любом случае, спасибо за ваше время!

Sergey Alexandrovich Kryukov

Добро пожаловать.
Я боюсь, что вы потратите некоторое время и придете к тому же самому выводу.
В любом случае, удачи,
--СА