2011-12-26 4 views
3

gcc 및 gfortran을 사용하여 혼합 언어 프로그래밍 (C/C++ 및 FORTRAN) 에 대한 질문이 있습니다. 나는 "포트란을 언어 X와 섞어서"검색했고 이것을 해결하지 못했습니다.C/C++, FORTRAN, 밑줄 및 GNU Autotools

링크 문제인지 컴파일러 문제인지 또는 둘 다 확실하지 않습니다.

세 파일을 만들었으므로 GNU Autotools를 사용하여 원시 응용 프로그램을 만들었지 만 명령 에서 독립적으로 응용 프로그램을 빌드 할 수 있어야합니다.

은 C 파일 (main.c의)는 여러 FORTRAN 함수 호출 구동 앱 될 것입니다 :

/* this is a simple program */ 

#include <stdio.h> 

/* add the extern function definition */ 
#include "fooonly.h" 

// this is not working for the mixed language programming stuff yet... 

/* this is the main program section */ 
int main(int argc, char *argv[]) 
{ 
    int a = 36; 
    int b = 24; 
    int c = 0; 

    printf("hi mom\n"); 

    /* now call a FORTRAN function from C */ 
    c = NGCD(&a, &b); 
    printf("NGCD(%d,%d)=%d\n", a, b, c); 

    return 0; 

}

가장 자주 FORTRAN 포함 포트란 기능을 77 (그러나 FORTRAN90/95 코드도 포함될 수 있음) : 다음과 같이 보입니다.

c$$$  The following introductory example in FORTRAN 77 finds the 
c$$$  $  greatest common divisor for two numbers A and B using a 
c$$$  $  verbatim implementation of Euclid's algorithm. 

     FUNCTION NGCD(NA, NB) 
     IA = NA 
     IB = NB 
1 IF (IB.NE.0) THEN 
     ITEMP = IA 
     IA = IB 
     IB = MOD(ITEMP, IB) 
     GOTO 1 
     END IF 
     NGCD = IA 
     RETURN 
     END 

Using Dev. Studio 6/Compaq Digital Fortran 6.0이 제대로 작동합니다. 사실, 나는 IFDEF 마치 #define를 사용할 필요가 없습니다 __cplusplus/# ENDIF 및 단순히처럼 보이는 C 파일을 만들 수 있습니다

/* this is a simple program */ 

#include <stdio.h> 

/* add the extern function definition */ 
extern "C" int __stdcall NGCD(int *a, int *b); 

/* this is the main program section */ 
int main(int argc, char *argv[]) 
{ 
    int a = 36; 
    int b = 24; 
    int c = 0; 

    printf("hi mom\n"); 

    /* now call a FORTRAN function from C */ 
    c = NGCD(&a, &b); 
    printf("NGCD(%d,%d)=%d\n", a, b, c); 

    return 0; 
} 

을하고 FORTRAN은 위의 응용 프로그램 링크를 목록으로 컴파일 , 이 실행되고 올바른 결과가 생성됩니다.

macbook:makecheck $ make 
gcc -DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE=\"fooonly\" -DVERSION=\"1.0.2\" -I.  -g -O2 -MT main.o -MD -MP -MF .deps/main.Tpo -c -o main.o main.c 
mv -f .deps/main.Tpo .deps/main.Po 
gfortran -g -O2 -o fooonly main.o ngcd.o 
Undefined symbols for architecture x86_64: 
    "_NGCD", referenced from: 
     _main in main.o 
ld: symbol(s) not found for architecture x86_64 
collect2: ld returned 1 exit status 
make: *** [fooonly] Error 1 
macbook:makecheck $ 

이 (GNU Autotools가에 의해 생성 된) 메이크가 기본적으로 포함되어 내가는 MinGW 또는 OSX에 GNU Autotools가를 사용하여이 과정을 최고 반복 할 때

C:\fooonly>fooonly.exe 
hi mom 
NGCD(36,24)=12 

C:\fooonly> 

, 나는 다음과 같은 오류가 계속 다음 명령을

:

macbook:makecheck $ gcc -c main.c 
macbook:makecheck $ gfortran -c ngcd.f 
macbook:makecheck $ gcc -o fooonly main.c ngcd.o 
Undefined symbols for architecture x86_64: 
    "_NGCD", referenced from: 
     _main in cc9uPBWl.o 
ld: symbol(s) not found for architecture x86_64 
collect2: ld returned 1 exit status 
macbook:makecheck $ 

내 configure.in 스크립트보다 아무것도 더 포함되어 있지 않습니다 본질적으로

AC_INIT(main.c) 
AM_INIT_AUTOMAKE(fooonly, 1.0.2) 

## C/C++ compiler section 
AC_PROG_CC 

## fortran section 
AC_PROG_F77 

## output section 
AC_OUTPUT(Makefile) 

,

macbook:makecheck $ gcc -c main.c 
macbook:makecheck $ gfortran -c ngcd.f 
macbook:makecheck $ gcc -o fooonly main.c ngcd.o 

맞죠? 내가 여러 플랫폼 (리눅스, Win32에서/64, OSX, 등)에 구축을 위해 노력하고 GNU Autotools입니다을 사용하려면, 나는이 다른 오픈 소스 프로젝트 수행 알고 있지만있어

그 프로젝트에 대한 configure.in 스크립트는 내 GNU Autotools 초보자를 초월한 방법이며, 은 디코드를 거의 시도하지 않습니다.

내가이 함께 할 수있는 뭔가가 추측하고있어 : 2)이 스위치 을 일부 마법의 세트를 포함하고 있지 않다,

1) 나는 configure.in 스크립트에서 사용한 정의를 (즉, -fno-second-underscore?) 또는 3) 두 가지 조합?

나는 닫을 수 있습니까? 그렇다면 앱을 빌드하려면 어떻게해야합니까?

+0

"macbook : makecheck $ gcc -o fooonly main.c ngcd.o"'main.c'보다는'main.o'를 더 잘 전달하지 않아야합니까? –

+0

예, 그렇습니다. 그것은 오타였습니다. – user1116524

답변

4

컴파일러가 최신 버전 인 지난 몇 년 동안 ISO C 바인딩을 사용하여 Fortran을 다른 언어와 혼합하는 것이 좋습니다. 그런 다음 언더 스코어 및 유사한 컴파일러/플랫폼 종속 문제로 이름 변경을 건너 뛸 수 있습니다. 변경하고 싶지 않은 기존의 FORTRAN 77 코드가 있다면 C와 FORTRAN 77 사이에 작은 Fortran 2003 glue 루틴을 작성할 수 있습니다. 이전 지침에는 내부 인터페이스에 대한 더 많은 이해가 필요했던 이전 방법이 설명되어 있습니다. 컴파일러/플랫폼에 따라 다릅니다. 새로운 방법에 대해서는 gfortran 매뉴얼 장 "혼합 언어 프로그래밍"과 이전의 질문/답변을보십시오.

포트란 코드를 사용하면 포트란 런타임 라이브러리를 가져 오기 때문에 gfortran과 연결하는 것이 더 쉽습니다. 나는 C++에도 똑같이 적용된다고 생각한다. 그래서 둘 다 가지고 있다면 명시 적으로 하나 또는 그 이상의 런타임 라이브러리를 포함시켜야 할 것이다.

P.

function NGCD (na, nb) bind (C, name="NGCD") 
    use iso_c_binding 
    implicit none 
    integer (c_int) :: ngcd 
    integer (c_int), intent (in) :: na, nb 
    integer (c_int) :: ia, ib, itemp 
    ia = na 
    ib = nb 

    do while (ib /= 0) 
     itemp = ia 
     ia = ib 
     ib = mod(itemp, ib) 
    end do 

    ngcd = ia 

    return 
end function NGCD 

컴파일/링크 : 여기에 바인딩 포트란 ISO C를 사용하는 예입니다 내가 충분한 대답을 얻었다 결코

gcc -c main.c 
gfortran main.o ngcd.f90 
+0

훌륭한 솔루션이며 앞으로는 공동 작업자에게 제안 할 것이라고 생각합니다. 불행히도 F77이 필요한 레거시 코드로 작업하고 있습니다. – user1116524

+0

때때로 레거시 프로그램이 F77을 유지해야한다는 요구 사항을 이해하지 못합니다. 나 자신은 f95 만있는 프로그램을 유지하지만 f77은 너무 쓸모가 없다. 최신 Fortran 표준의 기능은 이전 프로그램의 고정 형식 소스 코드에서 문제없이 사용할 수 있습니다. 역사적인 플랫폼과 메인 프레임 외부의 F77 만 알고있는 Fortran 컴파일러를 찾는 것은 어렵습니다. –

-1

는, 그래서 임시 해결책 함께 자갈길합니다 (FORTRAN에서 소문자를 무시 코드)에 게시하고 내 forufus 블로그에 게시했습니다. 앞으로 컴파일러 스위치를 해결해야 할 것입니다.