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

测试.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

谢谢, Kshitij

4

3 回答 3

5

您的常量是错误的,因为权限通常以八进制指定。试试这个程序:

#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 模式=384

600 八进制等于 384 十进制。

于 2011-09-24T22:02:40.433 回答
2

open期望你给它一个八进制的模式值,而不是十进制的(这就是为什么在 C 代码中处理模式时你基本上总是看到一个额外的前导零,因为在 C 中你写一个带有前导零的八进制文字)。

十进制的 600 是八进制的 1130。1130 对应于---x-wx--T,您可能有一个 022 的 umask,留下---x--x--T.

我相信您可以像这样在 Fortran 中指定一个八进制值:(o'600'即字母 o,然后是单引号内的八进制值)。或者,正如大卫施瓦茨在他的回答中所建议的那样,您可以只使用您想要的模式的十进制等价物。不过,当您稍后回顾它时,这可能会令人困惑。

编辑:MSB 指出,虽然 GNU Fortran 可能更宽松,但要遵守标准,您必须在声明中声明一个八进制常量data或(自 Fortran 2003 起) as int(o'600')

于 2011-09-24T22:08:11.333 回答
2

这是一个使用 Fortran ISO C 绑定作为 Fortran 和 C 部分之间的标准和可移植接口的示例。在我的计算机上,我发现 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 回答