2017-01-06 14 views
0

Fortranから呼び出されたCで関数を作成しようとしています。最初のものが最初に。 fortranコードはf77でコンパイルされ、cはgccでコンパイルされます。どちらも.soライブラリにコンパイルされます。 c関数は、Fortranで指定されたアドレスとサイズのデバイス上のメモリを読み込みます。私はアドレスを見ることができ、サイズはcに渡されていますが、私はc関数のデータを埋めてfortranに返すのに問題があります。以下の関連コードを参照してください。私の前提は、データ変数のメモリ割り当てやポインタ構文に何か問題があるということです。ポインタでFortranからC関数を呼び出す

C

void copymemory_(uint32_t *addr, int *size, uint8_t *data) 
{ 

    int i; 
    printf("addr %x \n", *addr); 
    printf("size %i \n", *size); 

    for (i = 0; i<*size; i++) 
    { 
     *data[i] = i; 
     printf("memory %i \n",*data[i]); 
    } 

} 

Fortranの

integer memory(4) 
call copymemory(z'dead', 4, memory) 

DO i = 1,memsize 
    call printf(memory(i)) 
END DO 
+1

は、なぜあなたは何かが間違っていると思いますか?何が起こるのですか? Fortran側では、 'memsize'と' printf'とは何ですか?そして 'z'dead''はどこにいますか? C側で、なぜ 'uint8_t'ですか?標準のFortran-C相互運用性を使用できないのはなぜですか? – francescalus

+0

よく仲間ですが、これは呼び出し規約にかなり依存しています...私は一生を通してFortranコードを書いたことはありませんでしたが、今は試してみます – DrPrItay

+0

エラーメッセージはありますか?どれ?間違った結果が印刷されますか?彼らはどのように見えるのですか? –

答えて

2

私はあなたのコードには、いくつかのポイントがあります。

コンパイル可能なコードを入力し、その正確なコードの出力を記述してください。

これには、標準ヘッダー用の#includeが含まれています。コードをデバッグしたい場合は、ユーザーが「明白」と思われたために省略した行を検索する必要がないようにします。ちょうどすべてを貼ります。ここからコピーするとコードがコンパイルされるはずです!

コードの実行可能部分であっても、私のコンパイラではコンパイルされません。 *datadataに変更する必要がありました。実際のコードをコピーしてもよろしいですか?

cfun.c: In function ‘copymemory_’: 
cfun.c:13:9: error: invalid type argument of unary ‘*’ (have ‘int’) 
     *data[i] = i; 
     ^
cfun.c:14:31: error: invalid type argument of unary ‘*’ (have ‘int’) 
     printf("memory %i \n",*data[i]); 
         ^

あなたのFortranコードには、printfサブルーチンの呼び出しが含まれています。これはどこに定義されていますか?あなたの実際のコードには存在しますか?私はそうは思わない。 StackOverflowに常に完全でコンパイル可能なコードをコピーしてください。

だから、明らかに固定した後、あなたの現在のコードは次のとおりです。

#include <stdio.h> 
#include <stdint.h> 

void copymemory_(uint32_t *addr, int *size, uint8_t *data) 
{ 

    int i; 
    printf("addr %x \n", *addr); 
    printf("size %i \n", *size); 

    for (i = 0; i<*size; i++) 
    { 
     data[i] = i; 
     printf("memory %i \n",data[i]); 
    } 

} 


implicit none 

integer :: memsize = 4 

integer memory(4) 
integer i 

call copymemory(z'dead', 4, memory) 

DO i = 1,memsize 
    print *, (memory(i)) 
END DO 

END 

それはクラッシュしませんが、Fortranでmemoryはゴミが含まれています。それはintegerであり、Cでint8_tと扱っているからです。

したがって、Cで4つの整数の配列として扱うか、1バイトずつコピーしますが、正しい数を渡す必要があります。コピーするバイト数。あなたの説明から、あなたの意図であるので、私はただ一つの可能​​性が表示されますどちら明らかではない。

void copymemory_(uint32_t *addr, int *size, uint32_t *data) 

を出力が正しいです:

> gfortran-4.10 -fsanitize=address cfun.c ffun.f90 
> ./a.out 
addr dead 
size 4 
memory 0 
memory 1 
memory 2 
memory 3 
      0 
      1 
      2 
      3 
+0

さらに多くの研究をした結果、私の目的には実際には解決策がないことがわかりました。私がf77コンパイラを使用していなかった場合、あなたが提供した解決策は正しいと思います。 f77はcからfortranに渡すことを許可しておらず、あなたが指定したコードを使用すると、fortran配列は常にその中にガベージを持っていました。私がf90を使うことができれば、あなたが提供したソリューションはうまくいくでしょう。 – cwheat

+0

すべてのコンパイラには独自の呼び出し規約があります基本的にはすべてのF77コンパイラがこれを許可していますが、* "F77コンパイラ" *はありませんが、コンパイラが多数あります。これはF77とF90の違いではなく、これは1つのコンパイラ対異なるコンパイラです。私の解決策は標準F90ではなく、gfortran特有のものです。標準のF90ソリューションはありません。標準的なC-Fortranの相互運用性はF2003です。 –

関連する問題