首页 > 解决方案 > Fortran、C++ API 的意外行为

问题描述

我为我的 C++ 代码开发了一个 Fortran API。从 Fortran 中,我将一个字符串传递给我绑定到的 C++ 函数,但接收到的字符串是非常出乎意料的。

我的 API 在以下模块中(api.f)

    module API

          use, intrinsic          :: ISO_C_Binding, only: C_double, c_char
          use, intrinsic          :: ISO_C_Binding, only: C_int
          use, intrinsic          :: ISO_C_Binding, only: C_ptr, C_NULL_ptr


          implicit none

    !     - Type object which binds to class object                                                                                      

          type     dp_t
          private
          type(C_ptr)             :: object = C_NULL_ptr
          end type dp_t

    !------------------------                                                                                                                      
    ! C function declarations                                                                                                                      
    !------------------------                                                                                                                      

          interface

             function  newcase_c (path, lenpath) result(this)
         &        bind(C, name="newcase")
             import

             type(C_ptr)                                    :: this
             character(kind=c_char)                         :: path(*)
             integer(kind=c_int)                            :: lenpath
             end function newcase_c
          end interface
      public     :: newcase_c, walldistance_c, releasemem_c
      public     :: dp_t

      CONTAINS

! Fortran wrapper routines to interface with C_wrappers                                                                                        

      subroutine newcase(this, path)

      type(dp_t), intent(out)        :: this
      character(:, kind=c_char),
     &     allocatable                     :: path
      integer(kind=c_int)                  :: sizepath

      write(*,*) "Trim Path: ", path, ":"
      write(*,*) "Len      : ", len(path)
      sizepath = len(path)
      this% object = newcase_c(path, sizepath)

      end subroutine newcase

    end module API

我在某处调用newcase如下所示main.f

      character(256, kind=c_char)   :: cwd
      character(:, kind=c_char)
     & , allocatable                :: trimpath
      type(dp_t)              :: dc

      call GETCWD(cwd)
      trimpath = trim(cwd)

      call newcase(dynacase, trimpath)

在我的.hpp文件中,我声明了我的C函数。注意 DP 是一个class.

#ifdef __cplusplus
extern "C" {
#endif
    DP * newcase(char *dir, int lenpath);
#ifdef __cplusplus
}
#endif

在我的.cpp我定义我的功能newcase为:

DP * newcase(char *dir, int lenpath){
    std::string path = "";
    for(int i=0; i<lenpath; i++){
        path += dir[i];
    }
    std::cout << "Received path :" << path << ":" << std::endl;
    fs::path runDir(path);
    return new DP(runDir);
}

问题是有时,newcase(.cpp)收到的字符串与预期的一样:

Trim Path: /Users/abcdef/test_cases:
 Len      :           24
Received string /Users/abcdef/test_cases:

有时这完全出乎意料:

Trim Path: /Users/abcdef/test_cases:
 Len      :           24
Received string /Users/abcdef/test_casesG.stl:

我的预感是字符串的空终止可能与此有关,我不确定如何解决这个问题。我该如何解决这个问题?更清楚地说,为什么*dir(.cpp) 与path(.f)不同newcase_c

建议的副本是:

ISO_C_BINDING 从 Fortran 调用 C 例程(使用双精度和数组)

虽然那里提出的解决方案解决了我的问题(因为我可以提取字符串的正确长度),但它没有谈论为什么我的 C++ 库接收的字符数组与 Fortran 传递的字符数组不同。

标签: c++cfortran

解决方案


推荐阅读