c++ - 将字符串从 Fortran 传递到 C++

标签 c++ fortran

<分区>

我按照以下示例 (http://fortranwiki.org/fortran/show/Fortran+and+Cpp+objects) 将 C++ 代码改编为 Fortran,首先我尝试学习 Fortran 并在 Fortran 和 C++ 之间建立联系。

我修改了要将字符串从 Fortran 传递到 C++ 的代码

#include <iostream>
#include <string>

using namespace std;
class CWLiDAR {
    string name;

public:
    CWLiDAR(string);
};


CWLiDAR::CWLiDAR(string name)
{
    this->name = name;
}


/*
*/

/* C wrapper interfaces to C++ routines */
#ifdef __cplusplus
extern "C" {
#endif
CWLiDAR* CWLiDAR__new(string name)
{
    return new CWLiDAR(name);
}
void CWLiDAR__delete(CWLiDAR* This)
{
    delete This;
}
#ifdef __cplusplus
}
#endif

Fortran 包装器

module CWLiDAR_module
  use, intrinsic :: ISO_C_Binding!, only: C_int, C_ptr, C_NULL_ptr
  implicit none
  private
  type CWLiDAR_type
    private
    type(C_ptr) :: object = C_NULL_ptr
  end type CWLiDAR_type
  interface
    function C_CWLiDAR__new (name, name_len) result(this) bind(C, name = "CWLiDAR__new")
      import
      type(C_ptr) :: this
      character(name_len, kind=C_CHAR), intent(IN) :: name
      integer :: name_len
    end function C_CWLiDAR__new
    subroutine C_CWLiDAR__delete (this) bind(C, name = "CWLiDAR__delete")
      import
      type(C_ptr), value :: this
    end subroutine C_CWLiDAR__delete
  end interface
  interface new
    module procedure CWLiDAR__new
  end interface new
  interface delete
    module procedure CWLiDAR__delete
  end interface delete
  public :: new, delete, CWLiDAR_type
contains


! Fortran wrapper routines to interface C wrappers
  subroutine CWLiDAR__new(this, name, name_len)
    type(CWLiDAR_type), intent(out) :: this
    character(*) :: name
    integer :: name_len
    this%object = C_CWLiDAR__new(name, name_len)
  end subroutine CWLiDAR__new
  subroutine CWLiDAR__delete(this)
    type(CWLiDAR_type), intent(inout) :: this
    call C_CWLiDAR__delete(this%object)
    this%object = C_NULL_ptr
  end subroutine CWLiDAR__delete
end module CWLiDAR_module

主要

program main
  use cwlidar_module
  type(CWLiDAR_type) :: lidar
  call new(lidar, "Test", 4)

  call delete(lidar)
end program main

我应该如何修改 Fortran 包装器以将字符串从 Fortran 传递到 C++?

最佳答案

首先,你不能在 Fortran 和 C 之间的接口(interface)使用 std::stringstd::string 是一些 C++ 实现定义的对象,没有保证与 Fortran 互操作性的内存布局。

您必须改用纯 C 字符串。因此,CVLiDAR__new() 必须接受类型为 char* 的参数,并且 Fortran 接口(interface)必须将此参数声明为

character(kind = c_char) :: name(*)

Fortran 包装例程必须采用一些 Fortran character 伪参数,然后继续将其内容复制到适当分配的 character(kind = c_char) 数组中,然后传递给 C 函数。

此时,您的 C 接口(interface)函数可能会继续将其再次转换为 C++ std::string。这种转换是可选的,因为 C++ 可以像 C 一样处理 C 字符串。不过,添加转换将使其余代码更纯 C++。

在 Fortran 端组装 C 字符串时,不要忘记以零字符正确终止它!


这些参数转换确实是一个 PITA,如果您有任何数量的接口(interface)函数需要从 Fortran 调用,那么编写生成 Fortran 包装器的生成器脚本可能是明智的。此类脚本的示例可在文件 cdi-1.8.1/interfaces/f2003/bindGen.rb< 中的气候数据接口(interface)库(CDI,源代码可在 https://code.mpimet.mpg.de/projects/cdi/files 中找到)中找到,它的输出发布在 cdi-1.8.1/src/mo_cdi.f90 下的同一个 tar 包中。这个脚本对于您的案例来说可能完全矫枉过正,但它对于 CDI 来说工作得很好,它的输出可能会启发/帮助您了解如何正确进行转换。

关于c++ - 将字符串从 Fortran 传递到 C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44780654/

相关文章:

python - 快速读取Python中的列分隔文本数据

python - 将 fortran 文件导入 python

c++ - 为什么 C++ 使用 memset(addr,0,sizeof(T)) 来构造一个对象?标准错误还是编译器错误?

python - 如何在f2py中链接FFTW3?

c++ - 通过引用传递后字符串发生变化

c++ - linux C++ : libaio. h 不包含 io_context _t 的定义?

gdb - 使用 gdb 和 gfortran 进行调试 - FPE

c++ - 在 Rcpp 中包装一个 Fortran 函数

c++ - 将数据存储在指针的最高有效位中

c++ - 有什么方法可以通过其成员名称索引hana适应的结构?