从Fortran调用C函数,其中C函数名最初是从C传入的 [英] Calling a C function from Fortran where the C function name was originally passed in from C

查看:244
本文介绍了从Fortran调用C函数,其中C函数名最初是从C传入的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

出于不相关的原因,我需要将C/C ++函数名称传递到Fortran子例程中,该子例程又调用该C函数.我发现我可以成功地将函数名称传递到Fortran子例程中.在该子例程中,我可以调用正确的C函数.但是,C函数的参数在此调用中被破坏(直接从C调用时,它可以正常工作).我使用了 ISO C绑定来尝试使其工作,无济于事.

For reasons that are not relevant, I need to pass a C/C++ function name into a Fortran subroutine, which, in turn, calls that C function. What I have found is that I can succesfully pass the function name into the Fortran subroutine. In that subroutine I can call the correct C function. However, the arguments of the C function get broken on this call (when called directly from C it works fine). I have used ISO C Binding to try and get this to work, to no avail.

这是MWE:

extern "C" {
    void fortranRoutine_(void(int status));
};


fromfromFortran.h:

void calledfromFortran(int status);


main.cpp:

#include "fortranRoutine.h"
#include "calledfromFortran.h" 

using namespace std;

int main(int argc, char** argv) {
    calledfromFortran(12);
    fortranRoutine_(calledfromFortran);
    return 0;
}


fortranRoutine.f90:

subroutine fortranRoutine(calledfromFortran)

    use iso_c_binding

    implicit none

    interface
        subroutine calledfromFortran(status) bind (c)
            use iso_c_binding
            integer(kind = c_int), intent(in) :: status
        end subroutine calledfromFortran
    end interface

    integer(kind = c_int) :: one

    one = 2
    call calledfromFortran(one)
    return

end subroutine fortranRoutine


fromfromFortran.cpp:

#include <iostream>
#include "stdlib.h"

using namespace std;

void calledfromFortran(int status) {
    cout << "In calledfromFortran:" << endl;
    cout << " status: " << status << endl;
}


当前结果

当前运行此操作可获得:


Current results

Running this currently gives:

In calledfromFortran:
 status: 12
In calledfromFortran:
 status: -1641758848

maincalledfromFortran的第一次调用正常工作,但是从fortranRoutine调用时,该值被破坏.请注意,每次运行时,后者的值都会更改.我在做什么错了?

The first call to calledfromFortran from main works correctly, but when it's called from fortranRoutine the value is broken. Note, each time it's run that latter value changes. What am I doing wrong?

推荐答案

在Fortran和C之间传递标量值时,基本上有两个选择:

When passing scalar values between Fortran and C, you have basically two options:

  • 您可以通过引用传递它们:在C端,您必须确保使用指向这些标量的指针.

  • You pass them by reference: On the C-side you have to make sure, that you use pointers to those scalars.

按值传递它们:在Fortran方面,必须确保使用VALUE属性,如其他文章所建议的那样.

You pass them by value: On the Fortran side you have to make sure that you use the VALUE attribute, as already suggested by other posts.

对于intent(in)属性,由于不影响变量是通过值还是通过引用传递,因此可以保留在该属性中.在Fortran中,除非您指定VALUE属性,否则参数始终通过引用传递.属性intent(in)仅告诉编译器防止在例程中使用该伪参数,否则会更改其值.

As for the intent(in) attribute, it can stay there, as it does not affect, whether the variable is passed by value or reference. In Fortran, arguments are always passed by reference unless you specify the VALUE attribute. The attribute intent(in) only tells the compiler to prevent a usage of that dummy argument in the routine, which would change its value.

有关命名的其他说明:您还应该用bind(c)指定Fortran例程fortranRoutine.这样,您就可以指定从C中看到的名称,即使它在模块内部也是如此:

Additional note on the naming: You should specify your Fortran routine fortranRoutine also with bind(c). This way you can specify its name as seen from C, even if it is inside a module:

module my_interface
  use iso_c_binding

contains

  subroutine fortranRoutine(calledFromFortran) bind(c, name='fortranroutine')
  ...
  end subroutine fortranRoutine

end module my_interface

通过这种方式可以确定,要从C调用的函数的名称为fortranroutine,而与编译器的约定无关,以在其后加上下划线,在模块名前添加名称或将名称转换为小写.因此,您将在C中有一个头文件,该头文件应独立地 compiler :

This way you can be sure, the name of the function to be called from C is fortranroutine, independent of the convention of the compiler to append underscores, prepend module names or convert names to lower case. Consequently, you would have a a header file in C, which should work compiler independently:

extern "C" {
  void fortranroutine(void(int status));
};

这篇关于从Fortran调用C函数,其中C函数名最初是从C传入的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆