0

C 関数を呼び出し、open() を使用してファイルを開く Fortran プログラムがあります。

main.f90:

PROGRAM TEST

    integer                        :: oflag, mode

    !Set oflag to O_CREAT|O_RDWR
    oflag = 66   
    mode = 600 

    call test2("test.txt", oflag, mode)

END PROGRAM

test.c:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>

#pragma weak test2_     = test2
#pragma weak test2__    = test2
#pragma weak TEST2      = test2

void test2(char* filename, int* flag, int* mode)
{
    int fd; 
    if(-1 == (fd = open(filename, *flag, *mode)))
        puts("Returned -1");
}

私は次のようにコンパイルします:

gcc -c test.c
gfortran main.f90 test.o

プログラムを実行すると、ファイル test.txt が作成されますが、権限が正しくありません。

---x--x--T 1 xyz users    0 2011-09-24 16:40 test.txt

あるべきだったとき

-rw------- 1 xyz users    0 2011-09-24 16:45 test.txt

この関数を別の C プログラムから呼び出すと、正常に動作します。誰かが何が間違っているのか指摘できますか?

仕様: 64 ビット Linux GNU Fortran (SUSE Linux) 4.5.0、GCC (SUSE Linux) 4.5.0

ありがとう、クシティジ

4

3 に答える 3

5

アクセス許可は通常 8 進数で指定されるため、定数が間違っています。このプログラムを試してください:

#include <stdio.h>
#include <fcntl.h>

int main(void)
{
 printf("oflag=%d mode=%d\n", O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);
}

私は得る:

oflag=66 mode=384

8 進数の 600 は 10 進数の 384 に相当します。

于 2011-09-24T22:02:40.433 に答える
2

これは、Fortran と C 部分の間の標準的で移植可能なインターフェースに Fortran ISO C Binding を使用した例です。私のコンピュータでは、O_CREAT|O_RDWR が異なる値、つまり 514 であることがわかりました。そのため、フラグを特定の値に設定しても移植性がありません。

PROGRAM TEST

    use iso_c_binding

    implicit none

    interface test2_interface

       subroutine test2 ( filename, flag, mode )  bind (C, name="test2")

       import

       character (kind=c_char, len=1), dimension (100), intent (in) :: filename
       integer (c_int), intent (in), VALUE :: flag, mode

       end subroutine test2

    end interface test2_interface


    integer (c_int) :: oflag, mode
    character (kind=c_char, len=100) :: filename


    !Set oflag to O_CREAT|O_RDWR
    oflag = 66  ! incorrect value ... not used
    mode = int ( o'600', c_int)

    filename = "test.txt" // C_NULL_CHAR

    call test2 (filename, oflag, mode)

END PROGRAM

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>

void test2(char* filename, int flag, int mode)
{
    int fd;
    printf ( "filename = '%s'\n", filename );
    flag = O_CREAT | O_RDWR;
    printf ( "flag = %d\n", flag );
    printf ( "mode = octal %o\n", mode );
    if(-1 == (fd = open(filename, flag, mode)))
        puts("Returned -1");
}
于 2011-09-25T06:42:41.107 に答える
2

openでは、モードの値を 10 進数ではなく 8 進数で指定する必要があります (これが、C コードでモードを処理するときに基本的に余分な先行ゼロが常に表示される理由です。C では先行ゼロを使用して 8 進数リテラルを記述するためです)。

10 進数で 600 は 8 進数で 1130 です。1130 は に対応し---x-wx--T、umask は 022 である可能性が高く、---x--x--T.

Fortran では、次のように 8 進値を指定できると思いますo'600'(これは、文字 o と単一引用符内の 8 進値です)。または、David Schwartz が彼の回答で示唆したように、必要なモードに相当する 10 進数を使用できます。後で振り返ると混乱するかもしれませんが。

編集: MSB は、GNU Fortran はより寛容かもしれないが、標準に準拠するには、dataステートメントまたは (Fortran 2003 以降) asで 8 進定数を宣言する必要があると指摘しましたint(o'600')

于 2011-09-24T22:08:11.333 に答える