⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 c_and_f.htm

📁 c/C++跟fortran语言之间的一些转换
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<DIV class=terminal><PRE>seaborg% <KBD> xlf90 -c f_main.f </KBD> 
** f_calls_c   === End of Compilation 1 ===
1501-510  Compilation successful for file f_main.f.
seaborg%  <KBD>xlC -c calc_cwrapper.C</KBD>
seaborg% <KBD>xlC -o f_calls_c++ calc_cwrapper.o f_main.o -lm -lxlf90</KBD>
seaborg% <KBD>./f_calls_c++</KBD>
Inside C function, creating C++ object
Inside C++ constructor
The distance between the points is 5 

Back in C function, will delete C++ object
Inside C++ destructor
</PRE></DIV>
<H3>Calling Fortran from C++</H3>
<P>You can call Fortran subroutines from C++ by declaring the routine </P><PRE>	extern "C" void <VAR>fortran_routine_name</VAR>
</PRE>or for Fortran functions <PRE>	extern "C" <VAR>return_type fortran_function_name</VAR>
</PRE>
<H2><A name=Calling_routines_in_Fortran_modules>Calling routines in Fortran 
modules</A> </H2>
<P>To call routines from C that are defined in Fortran 90 modules, you must 
refer to the Fortran <CODE>ROUTINE</CODE> as 
<CODE>__modulename_NMOD_routine</CODE>. </P>
<P>For example, the Fortran routine: </P>
<DIV class=code><PRE>! FILENAME: calc_mod_f.f
!
MODULE CALCULATION

      CONTAINS
        SUBROUTINE CALC_DIST(x1,y1,x2,y2)
        IMPLICIT NONE
        REAL :: x1,y1,x2,y2
        REAL :: distance

        distance = SQRT( (x2-x1)**2 + (y2-y1)**2 ) 

        WRITE(6,1) distance
1       FORMAT("The distance between the points is ", 1pe13.5) 

        END SUBROUTINE CALC_DIST 

END MODULE CALCULATION
</PRE></DIV>
<P>is called from the main C program in this way: </P>
<DIV class=code><PRE> 
/* FILENAME: c_main_mod.c
   Shows how to call a FORTRAN routine from C
   In this case the FORTRAN routine, named CALC_DIST,  
        is in the FORTRAN module named calculation
*/

extern void __calculation_NMOD_calc_dist(float *, float *, 
				float *, float *);

void main() 
{
        float p1_x,p1_y,p2_x,p2_y;

        p1_x = 0.0;
        p1_y = 0.0;
        p2_x = 3.0;
        p2_y = 4.0;

        __calculation_NMOD_calc_dist(&amp;p1_x,&amp;p1_y,&amp;p2_x,&amp;p2_y);
}
</PRE></DIV>
<P>Compiling and running: </P>
<DIV class=terminal><PRE>seaborg% <KBD> xlf90 -c calc_mod_f.f </KBD>
** calculation   === End of Compilation 1 ===
1501-510  Compilation successful for file calc_mod_f.f.
seaborg% <KBD>cc -o c_calls_f_mod c_main_mod.c calc_mod_f.o -lxlf90 -lm </KBD>
seaborg% <KBD>./c_calls_f_mod</KBD>
The distance between the points is   5.00000E+00
</PRE></DIV>
<H2><A name=characters>Working with characters</A> </H2>
<P>Passing characters and strings between Fortran and C is not straightforward. 
When Fortran passes a CHARACTER string, it passes (by value) an extra argument 
that contains the length of the string. In addition, C strings are usually 
null-terminated, while Fortran character strings are not. </P>
<P>To pass a Fortran <TT>CHARACTER</TT> to a C routine that accepts a 
<TT>char</TT>, the string must be null terminated. </P>
<P>The only character type in Fortran is CHARACTER, which is stored as a set of 
contiguous bytes, one character per byte. The length is not stored as part of 
the entity. Instead, it is passed by value as an extra argument at the end of 
the declared argument list when the entity is passed as an argument. </P>
<P>If you are writing both parts of the mixed-language program, you can make the 
C routines deal with the extra Fortran length argument, or you can suppress this 
extra argument by passing the string using the %REF function. If you use %REF, 
which you typically would for pre-existing C routines, you need to indicate 
where the string ends by concatenating a null character to the end of each 
character string that is passed to a C routine. </P>
<P>Following is an example that shows some correct and incorrect ways to pass 
and handle characters and strings from Fortran to C. </P>
<DIV class=code><PRE>!FILENAME: give_chars.f
!
! Gives some examples of passing Fortran strings to
! a C routine that prints a character string beginning
! at the address of the start of the passed character
! string and ending at the C string termination character, which is
! CHAR(0) in Fortran.
 
PROGRAM give_chars

        IMPLICIT NONE

        CHARACTER(LEN=1)::  a(9),d
        CHARACTER(LEN=8)::  b,c,e
        REAL:: f
        EXTERNAL TAKE_CHARS 
        
! These are put in COMMON block to insure they are all 
! adjacent in memory

        COMMON//b,c,d
        COMMON/c2/e,f

        a(1) = 'a'
        a(2) = 'b'
        a(3) = 'c'
        a(4) = 'd'
        a(5) = 'e'
        a(6) = 'f' 
        a(7) = 'g'
        a(8) = 'h'

! This behavior of this call is undefined, since there is
! no string terminator character being passed to the C
! routine. It will 'work' if there fortuitously happens to be
! a zero in the next memory location after a(8).
 
        PRINT *, ""
        PRINT *, "This may or may not print a(1) to a(8):"
        CALL TAKE_CHARS(a)


! This puts a string terminator character in a(6)

        a(6) = CHAR(0)  ! String terminator for C routine
        PRINT *, ""
        PRINT *, "This will print a(1) to a(5):"
        CALL TAKE_CHARS(a)

!
        b='ABCDEFGH'
        c='ijklmnop'
        d = CHAR(0)     !String terminator for C routine

!       The string terminator in d follows the string c in memory
!       but there is no string terminator character between c and d
!       (All this controlled by COMMON block declaration).

        PRINT *, ""
        PRINT *, "This will print string b and c:"
        CALL TAKE_CHARS(b)

!       Here we append a string terminator character to  the
!       string b when we pass it. 

        PRINT *, ""
        PRINT *, "This will print string b only:"
        CALL TAKE_CHARS(b // CHAR(0)) !Appends string terminator to b

!       The following will print string e plus garbage
!       because the C routine does not see a string terminator
!       before the REAL value f 

        e = 'abcdefgh'
        f = ATAN(1.)
        PRINT *, ""
        PRINT *, "This will print string e plus garbage:"
        CALL TAKE_CHARS(e)
         
                
END PROGRAM give_chars
</PRE></DIV>
<P></P>
<DIV class=code><PRE> 
/* FILENAME: take_chars.c
   A routine to take a Fortran character string
   and print it. It assumes that the Fortran routine
   has explicitly appended a string terminator character
   to the string before passing it.
*/


void take_chars(char *fstring, long int fstringLen)
{
        
/*      This printf() function (with %s) will print characters until
        it encounters a \0 character, which it interprets as an 
        end-of-string signal.
*/ 
         
        printf("The passed string is: %s\n",fstring);
        printf("The passed string length is: %d\n",fstringLen);
}
</PRE></DIV>
<P>Compile these routines with </P>
<DIV class=terminal><PRE>% <KBD> xlf90 -c give_chars.f</KBD>
% <KBD> cc -c take_chars.c </KBD> 
% <KBD> xlf90 -o give_chars give_chars.o take_chars.o </KBD> 
</PRE></DIV>
<P>When we run the program, we get: </P>
<DIV class=terminal><PRE>% <KBD> ./give_chars </KBD>
This may or may not print a(1) to a(8):
The passed string is: abcdefgh
The passed string length is: 1
 
 This will print a(1) to a(5):
The passed string is: abcde
The passed string length is: 1
 
 This will print string b and c:
The passed string is: ABCDEFGHijklmnop
The passed string length is: 8
 
 This will print string b only:
The passed string is: ABCDEFGH
The passed string length is: 9
 
 This will print string e plus garbage:
The passed string is: abcdefgh?I&Ucirc;
The passed string length is: 8
</PRE></DIV><A name=case></A>
<H2>Using mixed case names</H2>
<P>Sometimes you may want to link with code containing C/C++ routines that have 
mixed-case or upper-case names. You can use these routines by using the 
<TT>-U</TT> option when compiling with <TT>xlf</TT>. However, this makes all 
functions, variables, and names case-sensitive. </P>
<P>You can also use the <TT>@PROCESS MIXED</TT> directive to declare case 
sensitivity. For example: </P><PRE>@process mixed
	external C_Func	   ! now we can call C_Func, not just c_func
	integer aBc, ABC   ! now these are two different variables
	common /xYz/ aBc   ! the same applies to common block names -
	common /XYZ/ ABC   ! these two are different

	end
</PRE></BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -