简体   繁体   English

Fortran 和 C 互操作性:将 char *string 作为函数的参数传递给 Fortran

[英]Fortran and C interoperability: passing char *string as a function's argument to Fortran

I would like to create a fortran binding to a C function that returns an arbitrary length string as a function argument. I would like to create a fortran binding to a C function that returns an arbitrary length string as a function argument. I have read this similar question , but I simply cannot get the solution there to work.我已经阅读了这个类似的问题,但我根本无法让解决方案在那里工作。 I have simplified the problem as much as I can so I can explain here.我已经尽可能地简化了这个问题,所以我可以在这里解释一下。

I have a C function like this: c_string.c (I know that usually this kind of function would also have an argument that also returns the length of the string, but I have left it out here for simplicity, since in this example I know the length.) I have a C function like this: c_string.c (I know that usually this kind of function would also have an argument that also returns the length of the string, but I have left it out here for simplicity, since in this example I know长度。)

#include <string.h>

void make_string(char *string) {
    strcpy(string, "sand");
}

It seems to work fine in a C program, for example:它似乎在 C 程序中运行良好,例如:

#include <stdlib.h>
#include <stdio.h>
#include "c_string.c"

int main() {
    char *string;
    string = malloc(5*sizeof(char));
    make_string(string);
    printf(string);
}

I want to call this function in a Fortran program: main.f90.我想在 Fortran 程序中调用这个 function:main.f90。 So I make a c binding following the solution mentioned above.因此,我按照上述解决方案进行了 c 绑定。

program main
    use iso_c_binding
    implicit none
    interface
        subroutine c_make_string(string) bind (C, name='make_string')
            import
            type (c_ptr), value :: string
        end subroutine c_make_string
    end interface

    type (c_ptr) :: c_string
    character, pointer :: local_string(:)

    call c_make_string(c_string)
    call c_f_pointer(c_string, local_string, [4])
    write (*,*) local_string
end program main

But this program results is a segfault at the write statement.但是这个程序的结果是写语句处的段错误。 Trying to access the resulting local_string pointer by indexing gives a segfault too.尝试通过索引访问生成的local_string指针也会产生段错误。 Note: after adding the value attribute to the interface, the segfault is now in the C function.注意:将value属性添加到界面后,段错误现在在C function中。

The only solution I came up with is to not use c_ptr and c_f_pointer() , and just use a maximum buffer length like 512.我想出的唯一解决方案是不使用c_ptrc_f_pointer() ,而只使用像 512 这样的最大缓冲区长度。

program main
    use iso_c_binding
    implicit none

    interface
        subroutine c_make_string(string) bind (C, name='make_string')
            import
            character (len=1, kind=c_char) :: string(512)
        end subroutine
    end interface

    character (len=1, kind=c_char) :: local_string(512)

    call c_make_string(local_string)
    write (*,*) local_string
end program main

But that results in a whole bunch of junk after the useful data in the string.但这会在字符串中的有用数据之后产生一大堆垃圾。 Of course, that is easily worked around if you know the length of the intended string, but it feels unsatisfactory to me... if only I knew what was going wrong with the c_f_pointer() call in the original solution.当然,如果您知道预期字符串的长度,这很容易解决,但这对我来说并不令人满意......如果我知道原始解决方案中的c_f_pointer()调用出了什么问题。 Should I allocate space for the local_string before, as I do in the C program?我是否应该像在 C 程序中那样为local_string分配空间? But how?但是怎么做? Why does it seem I need fixed length arrays for the binding?为什么我似乎需要固定长度的 arrays 进行绑定? What is the clean solution to passing char * variables of arbitrary length via subroutine/function arguments?通过子程序/函数 arguments 传递任意长度的 char * 变量的干净解决方案是什么?

You do not allocate the memory for the string anywhere.您不会在任何地方为字符串分配 memory。 You are just passing an undefined pointer to the C function and then the C function tries to copy some character data to this undefined address. You are just passing an undefined pointer to the C function and then the C function tries to copy some character data to this undefined address.

Either pre-allocate the string in Fortran, pass its length to C and use strncpy or malloc the string in C but then you will have to free it from C. Either pre-allocate the string in Fortran, pass its length to C and use strncpy or malloc the string in C but then you will have to free it from C.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM