2013-07-24 30 views
5

我試圖編譯和鏈接Fortran代碼調用C子程序:調用C函數/子程序Fortran代碼

Fortran代碼:

program adder 
integer a,b 
a=1 
b=2 
call addnums(a,b) 
stop  
end program 

C代碼:

void addnums(int* a, int* b) 
{ 
    int c = (*a) + (*b); /* convert pointers to values, then add them */ 
    printf("sum of %i and %i is %i\n", (*a), (*b), c); 
} 

我使用以下命令在Windows環境中編譯和鏈接。

ifort -c adder.f 
cl -c addnums.c 
ifort -o add adder.obj addnums.obj 

我得到以下錯誤:

Microsoft (R) Incremental Linker Version 8.00.50727.762 
Copyright (C) Microsoft Corporation. All rights reserved. 
-out:add.exe 
-subsystem:console 
adder.obj 
addnums.obj 
adder.obj : error LNK2019: unresolved external symbol ADDNUMS referenced in function MAIN__ 
add.exe : fatal error LNK1120: 1 unresolved externals 

請幫我解決這個問題?謝謝。

+0

您是否嘗試過匹配該函數名稱(即全部大寫)? –

回答

10

您需要爲Fortran主程序的規範部分內的C函數提供一個接口體,它告訴Fortran編譯器名稱addnums是C函數。喜歡的東西:

INTERFACE 
    SUBROUTINE addnums(a, b) BIND(C) 
    USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_INT 
    IMPLICIT NONE 
    INTEGER(C_INT) :: a, b 
    END SUBROUTINE addnums 
END INTERFACE 

(通過這一平臺沒有特殊的選項對這些編譯器默認的那種整數相同c_int的 - 但作爲明確的關於整型種類有助於保護你,如果編譯器/平臺或編譯選項改變。 )

+0

謝謝。你的建議幫了忙。 – momba

2

這裏有兩件事情我可以看到了蝙蝠的權利(我的工作主要是與FORTRAN77所以這可能不會是這樣做),最新的或最好的方法:

  1. 因爲你的C函數,以及,一個函數(而不是子例程),你需要聲明'addnums'作爲EXTERNAL。將此添加到聲明部分的代碼中。

    EXTERNAL addnums
  2. 在您的C代碼中爲該函數的名稱添加下劃線。 FORTRAN會自動執行它自己的功能,但不會執行其他語言的功能。因此,函數的簽名會

    void addnums_(int* a, int* b)

This page對混合C和FORTRAN一個很好的破敗。希望這有助於!

+1

連接Fortran和C的現代方式是使用Fortran ISO_C_Binding。作爲Fortran語言的一部分,它是獨立於編譯器和平臺的。它避免了需要了解編譯器內部的知識。鏈接的頁面已過時。 –

+0

如果您無法使用ISO_C綁定,請將C例程聲明爲__stdcall,否則其默認爲__cdecl。它會在退出時調用你的例程並崩潰。 – cup

+0

指向「此頁面」的鏈接已中斷。 – Wauzl