将标量和数组(任意维度)从 Fortran 传递到 C

2024-03-17

我有以下名为的 Fortran 子例程show_value调用一个名为的 C 函数show_value:

INTERFACE
    SUBROUTINE show_value(variable) BIND(C, name = "show_value")
        USE, INTRINSIC :: iso_c_binding
        TYPE(*) :: variable
    END SUBROUTINE
END INTERFACE

C 函数show_value:

void show_value(const void *variable)
{
    printf("%d\n", *(int *) variable);
}

Fortran 子例程在向其传递标量时运行良好。例子:

INTEGER :: x
x = 12
call show_value(x)

这将调用 C 函数show_value并打印12, 哪个是对的。

现在,根据 Fortran 文档,如果想启用子例程show_value还接收数组(任何维度)而不仅仅是标量,该行TYPE(*) :: variable应该改为TYPE(*), DIMENSION(..) :: variable.

进行此更改后,执行以下 Fortran 代码时:

INTEGER, DIMENSION(3) :: y
y(1) = 15
y(2) = 17
y(3) = 19
call show_value(y)

C 函数show_value不再打印正确的消息(即打印随机数)。此外,我发现C函数接收的地址比原始地址(在Fortran中)低528。为了确认这一点:

void show_value(const void *variable)
{
    printf("%d\n", *(int *) (variable + 528));
}

...打印15(正确的数字)。

知道这里发生了什么吗?

环境:Ubuntu 14.04 64位,gfortran 4.9


尽管您的第一个案例带有标量参数,但可以正确匹配void*参数,当调用的参数被假设为等级时(其中type(*), dimension(..) :: variable表示)Fortran 过程与具有相应形式参数的 C 过程不可互操作const void *variable.

相反,有必要使用CFI_cdesc_t机制:

#include <stdio.h>
#include <ISO_Fortran_binding.h>

void show_value(const CFI_cdesc_t* variable)
{
  printf("%d\n", *(int*) variable->base_addr);
}

您可以在 Fortran 2018 18.5.3 中找到详细信息。

然而,本质上,这是一个包含 Fortran 实体的许多细节的描述符。这里,base_addr是数据的开始,但您还可以找到可分配/指针/数据状态、等级、范围、类型。

唉,gfortran 4.9 不支持这个。如果完全支持的话,也只会是最近的版本。


或者,您可以避免使用假定等级假定类型实际参数,并使用以下方法传递参数的 C 地址:c_loc。不太优雅,但得到更广泛的支持:

use, intrinsic :: iso_c_binding, only : c_loc, c_ptr, c_int
interface
  subroutine show_value(variable) bind(c)
    import c_ptr
    type(c_ptr), value :: variable
  end subroutine
end interface

integer(c_int), target :: x, y(3)

x = 12
y = [15, 17, 19]

call show_value(c_loc(x))
call show_value(c_loc(y))

end

然而,这留下了 C 函数如何知道如何处理参数的问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将标量和数组(任意维度)从 Fortran 传递到 C 的相关文章

随机推荐

  • UTC 和 Etc/UTC 时区之间有区别吗?

    在 PHP 文档中 支持的时区列表 http php net manual en timezones others php UTC被列出两次 UTC Etc UTC 这两者之间有概念上的区别吗 或者它们只是同义词 简短回答 NO 有没有不同
  • JCL 安装到 Delphi 10 西雅图时出错

    我正在尝试将 JCL JVCL 安装到 Delphi 10 Seattle 中 我收到以下错误 使用 Embarcadero RAD Studio 10 西雅图 Embarcadero Delphi for Win32 编译器版本30 0
  • PHP 浮动使用的最佳实践

    我读过浮点指南 http floating point gui de languages php 关于在 PHP 中使用 float 类型 答案是使用 BC Math 扩展 使用字符串可以将浮点数表示为精确类型 并防止浮点数和整数问题 同时
  • 从 VBA 中的不同模块调用子例程

    是否可以从一个函数调用一个函数Module到另一个 我有以下代码 Sub MAIN Call IDLE End Sub MAIN位于Module1 IDLE位于Module2并定义为 Sub IDLE 在调用前加上 Module2 前缀 例
  • 使用 SUMO 场景的子集进行 OMNeT++ 网络模拟(使用 VEINS)

    我正在尝试使用 OMNeT Veins 和 SUMO 评估在车载网络上运行的应用程序 因为该应用程序依赖于现实的流量行为 所以我决定使用LuST场景 https github com lcodeca LuSTScenario 这似乎是此类数
  • glewInit() 失败,OpenGL 应用程序

    我正在尝试使用 glew glfw 构建一个 OpenGL 应用程序 我已经下载了二进制文件 将它们放在文件夹的根目录中 添加了 include 和 lib 目录的路径 并告诉我的项目需要 glew32 lib GLFW lib 和 ope
  • Delphi XE AnsiStrings 带有转义组合变音符号

    将包含转义组合变音标记 如 Fu u0308rst 的 Delphi XE AnsiString 转换为友好的 WideString F rst 的最佳方法是什么 我知道这并不总是适用于所有组合 但应该支持常见的拉丁语块 而无需自己构建愚蠢
  • WP7 - 水平滚动列表框的问题

    我需要一个水平滚动的列表框 并且我遵循了与此相关的其他几个问题提出的关于如何实现的建议 我目前所拥有的确实水平滚动 但在滑动结束时 它不会停留在我滚动到的位置 它会恢复到原始显示 有点像它的一块松紧带 在滑动后返回到其原始位置它被拉伸了 我
  • 使用dispatchEvent获得焦点事件

    当我触发一个focus事件与dispatchEvent在输入框上 其onfocus被调用 但在 UI 上输入框未获得焦点 这种行为有什么原因吗 var test document getElementById test test onfoc
  • 是否可以部分解码和更新 JSON? (去)

    我只需要解码和更新 json 对象的特定值 问题是我不知道该对象的完整结构 coding json 包 忽略 截断结构中未提供的字段 因此对这些字段进行编码会丢失 我想知道是否可以只解组我知道的结构 更新它 然后编组它 而不截断 删除未知的
  • 登录 Facebook 后如何重定向 url?

    我创建了一个 Django 应用程序 并通过 Facebook 连接到该应用程序 现在 当我单击 Facebook 登录按钮时 会弹出 oauth 页面 当我提供用户名和密码时 它会关闭 而不会实际将页面重定向到任何页面 但是当我在新选项卡
  • 如何避免graphviz中的重叠节点?

    我正在尝试绘制一个包含许多节点和边的图 然而 该图变得过于笨拙 节点和边重叠 我尝试了 未成功 以下所有方法或这些方法的组合 size 12 0 20 0 margin 0 0 len 1 0 我在用neato生成一个 png 文件 尺寸规
  • 删除一行后如何刷新jquery数据表

    数据表中的每一行都有一个删除按钮 单击删除按钮后 我将调用以下代码 deleteButton live click function var this this var url this attr id example fnReloadAj
  • 如何在 ASP.Net CreateUserWizard 中获取新注册用户的用户 ID?

    如何在 ASP Net CreateUserWizard 中获取新注册用户的用户 ID 我有一个页面允许新用户使用 创建用户向导 进行注册 创建用户后 我想使用新用户的用户 ID 和电子邮件在客户详细信息表中插入一行 我尝试在 Create
  • 如何使用 KivyMD 在 NavigationDrawer 内的屏幕之间切换

    我是使用 kivymd 的初学者 并尝试使用 KivyMD 在 NavigationDrawer 内的屏幕之间切换 我正在阅读一些文档并最终得到了这段代码 但它对我不起作用 from kivy lang import Builder fro
  • 可以在不使用 Heroku Toolbelt 的情况下部署 Rails 应用程序吗?如果是这样,怎么办?

    我想在不使用 Heroku ToolBelt 的情况下部署 Rails 应用程序 是否可以 如果是这样 怎么办 我只能使用 Heroku 仪表板 我不允许使用任何其他云服务 我必须运行 PostgreSQL 命令 添加附加组件并设置配置变量
  • firebase login:ci 是否可以访问我的所有项目?

    我正在使用firebase login ciCI CD 的代币 但没有足够的有关令牌的文档 它是否可以访问我的帐户有权访问的所有 Firebase 项目 还是只能访问当前活动的项目 我在哪里可以看到所有代币及其活动的列表 我想要的解决方案是
  • python read_fwf 错误:“python-fwf 解析器不支持 dtype”

    使用 python 2 7 5 和 pandas 0 12 0 我尝试使用 pd io parsers read fwf 将固定宽度字体文本文件导入到 DataFrame 中 我导入的值都是数字 但保留前导零很重要 因此我想将数据类型指定为
  • ORA-00979不是一个group by表达式

    我通过以下查询收到 ORA 00979 SELECT cr review sk cr cs sk cr full name tolist to char cf fact date mm dd yyyy appt cs cs id cr tr
  • 将标量和数组(任意维度)从 Fortran 传递到 C

    我有以下名为的 Fortran 子例程show value调用一个名为的 C 函数show value INTERFACE SUBROUTINE show value variable BIND C name show value USE