2014-07-13 4 views
3

안녕하세요 Fortran 90 코드를 사용하여 C 함수를 호출하고 있습니다. 주소를 조작하고 있기 때문에 C 함수의 인수는 Fortran에서 올바르게 일치해야합니다. 나는 코드를 컴파일하고 64 비트 머신에서 작업하기 위해 ifort와 icc를 사용하고있다.Fortran에서 C 함수를 호출하고 uint32_t 인수를 올바르게 전달하는 방법

일부 테스트는 최종 함정을 방지 할 수 있지만이 내가 전화하고있는 uint32_t

C 함수를 유지하고 싶은, int32_t로도 작동 것으로 나타났다 다음과 같은 프로토 타입을

uint32_t encode_(uint32_t x, uint32_t y) 
uint32_t decode_(uint32_t dec) 

I있다

integer :: cod,encode 
cod = encode(i,j) 

이렇게하면 이러한 기능을 호출 할 수 없습니다. 그러므로 나는이 해결 방법을 사용하고 있습니다 :

void code2d_(uint32_t j[]){ 


uint32_t i; 

i=encode_(j[0],j[1]); 
// the underscore is due to the FORTRAN naming convention 

printf("Coded %10d \n",i); 

} 

그리고 이후 포트란

integer :: cod,code2d 
cod = code2d(i,j) 

음에

을 분명히 내가 인수 형식의 불일치 몇 가지 문제가 있습니다. 불행히도이 문제를 해결하는 방법을 모르겠습니다. 디코 드/인코딩 함수에서 이진 주소 산술 연산이 수행되었으므로 uint32_t을 보존하는 것이 중요합니다.

답변

6

태그를 사용할 때 iso_c_binding에 대해 알고있는 것으로 보입니다. C.와의 Fortran 2003 상호 운용성을 연구하십시오. 태그 설명과 http://gcc.gnu.org/onlinedocs/gcc-4.9.0/gfortran/Interoperability-with-C.html과 같은 일부 문서를 읽으십시오. 꼬투리 밑줄과 유사한 것들에 대한 현대 Fortran에는 존재하지 않습니다.

Fortran에는 부호없는 유형이 없으므로 서명 된 코드를 사용해야합니다. 서명 된 값이 양수이면 작동합니다. 더 큰 값이 필요하면 큰 정수 유형을 사용하십시오. 필요한 경우 transfer()의 하위 바이트를 int32로 설정할 수 있습니다.

셋째, Fortran은 기본적으로 참조에 의한 여러 가지 변형을 사용합니다. 특히 bind(c) 절차 (사본 또는 다른 변형에 대한 참조 일 수 있음)의 경우. 값으로 전달하려면 value 속성을 사용해야합니다. 당신은 경고를 무시하거나 당신이 알고있는 경우이를 해제 할 수 있습니다

rng.f90:173:0: warning: type of 'sub' does not match original declaration [-Wlto-type-mismatch] 
    ival = sub(jz, jsr) 
^ 
rng_c.c:2:10: note: return value type mismatch 
uint32_t sub(uint32_t a, uint32_t b) { 
     ^
/usr/include/stdint.h:51:23: note: type 'uint32_t' should match type 'int' 
typedef unsigned int uint32_t; 
        ^
rng_c.c:2:10: note: 'sub' was previously declared here 
uint32_t sub(uint32_t a, uint32_t b) { 

: GCC의

uint32_t encode(uint32_t x, uint32_t y) 
uint32_t decode(uint32_t dec) 

module c_procs 
    interface 
    function encode(x, y) bind(C, name="encode") 
     use iso_c_binding 
     integer(c_int32_t) :: encode 
     integer(c_int32_t), value :: x, y 
    end function 
    function decode(x, y) bind(C, name="decode") 
     use iso_c_binding 
     integer(c_int32_t) :: decode 
     integer(c_int32_t), value :: dec 
    end function 
    end interface 
end module 

... 

use iso_c_binding 
use c_procs 

integer(c_int32_t) :: cod, i, j 
cod = encode(i,j) 

최신 버전 링크시 최적화 동안 우리는 서명과 서명되지 않은 유형을 혼합하는 것을 감지 할 수있다 당신이하고있는 일.

+0

의견과 매우 편리한 솔루션에 감사드립니다. 나는 ISO C 바인딩없이 작업을 끝내기를 희망했다. 이것은 FORTRAN 95 이상 기능이며 몇 가지 문제가 발생할 수 있습니다. 예를 들어, 빠른 배열 작업을 위해 많은 F77을 사용합니다. 나는 메모리 할당을 위해 C를 사용하고, 보통의 바인딩은 이름을 붙일 수있는 것처럼 아주 깔끔하게 (밑줄로) 작동한다. 어쨌든 나는 현대 FORTRAN에 의지하고 ISO C 바인딩을 사용할 것이다. BTW 두 번째 인터페이스에서'정수 (c_int32_t) :: decode'해야합니다 감사합니다 블라디미르! –

+2

밑줄은 항상 바인딩 이름에 사용하면됩니다. 당신은 또한 포인터를 받아들이도록 C 절차 변경을 고칠 수 있습니다. 어떤 경우에는 인터페이스를 정확히 준수해야합니다. Fortran-C 바인딩은 매우 효율적이므로 성능에 대해 걱정하지 않아도됩니다. –