在Visual Studio中将变长c字符串转换为Fortran字符串

在Visual Studio中将变长c字符串转换为Fortran字符串,c,arrays,string,visual-studio,fortran,C,Arrays,String,Visual Studio,Fortran,我需要将C字符串转换为Fortran字符串。在使用英特尔Visual Fortran Composer XE 2013在Visual Studio 2012中调试示例代码时,我遇到了几个问题: 1) 我在调试器中看不到延迟长度可分配字符变量(str)的值 2) 在代码中放置断点时,分配此变量类型会导致fCode.pdb文件锁定。释放文件的唯一方法是关闭句柄(通过Process Explorer)或关闭IDE 我在代码中遗漏了什么吗?释放内存?有没有更干净的方法来进行转换 C代码 int main

我需要将C字符串转换为Fortran字符串。在使用英特尔Visual Fortran Composer XE 2013在Visual Studio 2012中调试示例代码时,我遇到了几个问题:

1) 我在调试器中看不到延迟长度可分配字符变量(
str
)的值

2) 在代码中放置断点时,分配此变量类型会导致fCode.pdb文件锁定。释放文件的唯一方法是关闭句柄(通过Process Explorer)或关闭IDE

我在代码中遗漏了什么吗?释放内存?有没有更干净的方法来进行转换

C代码

int main ( void ) {

    char* cstr = "BP1000";

    c_to_f(cstr);

    return 0;
}
Fortran代码

module mytest
    contains

    subroutine c_to_f(cstr)  BIND(C, name="c_to_f")
    use, intrinsic :: iso_c_binding    
    !DEC$ ATTRIBUTES DLLEXPORT :: c_to_f

    character(kind=C_CHAR, len=1), intent(IN) :: cstr(*)    
    character(:), allocatable :: str

    str = c_to_f_string(cstr)

    end subroutine c_to_f  

    function c_to_f_string(s) result(str)
      use, intrinsic :: iso_c_binding
      character(kind=C_CHAR, len=1), intent(IN) :: s(*)
      character(:), allocatable  :: str
      integer i, nchars
      i = 1
      do
         if (s(i) == c_null_char) exit
         i = i + 1
      end do
      nchars = i - 1  ! Exclude null character from Fortran string
      allocate(character(len=nchars) :: str)
      str = transfer(s(1:nchars), str)
    end function c_to_f_string

end module mytest   
1) 查看Fortran模块中的变量:使用modulename::variablename。您正在运行调试版本还是发布版本?如果正在运行发布版本,请打开项目属性中的符号。如果您正在运行调试版本,.pdb是否与可执行文件位于同一目录中?如果您正在使用Fortran和C语言,那么将有两个pdb文件。所有DLL和EXE必须位于同一目录中。要自动实现这一点,请更改项目设置。而不是

+ solution
  +-- C program
      +-- debug (both $IntDir and $OutDir point here)
  +-- Fortran lib
      +-- debug
换成

+ solution
  +-- debug (change the project output $OutDir to this place)
  +-- C program
      +-- debug ($IntDir remains here)
  +-- Fortran lib
      +-- debug ($IntDir remains here)
还要将.pdb位置更改为$(OutDir)$(TargetName).pdb。默认值为$(IntDir)vc100.pdb(或visual studio版本的10倍)

2) 重新锁定。无论何时添加断点并运行,pdb文件都将锁定。如果程序未运行,则它们不应锁定,除非您的VS版本已将其锁定。是否已应用VS SP?另外,确保C程序和Fortran程序具有相同的调用约定。有stdcall和cdecl。在Fortran中,这是在项目设置中完成的。如果没有传递任何参数,这无关紧要,但在传递参数时,请确保两者使用相同的约定

有关stdcall和cdecl之间的差异,请参阅查看Fortran模块中的变量:使用modulename::variablename。您正在运行调试版本还是发布版本?如果正在运行发布版本,请打开项目属性中的符号。如果您正在运行调试版本,.pdb是否与可执行文件位于同一目录中?如果您正在使用Fortran和C语言,那么将有两个pdb文件。所有DLL和EXE必须位于同一目录中。要自动实现这一点,请更改项目设置。而不是

+ solution
  +-- C program
      +-- debug (both $IntDir and $OutDir point here)
  +-- Fortran lib
      +-- debug
换成

+ solution
  +-- debug (change the project output $OutDir to this place)
  +-- C program
      +-- debug ($IntDir remains here)
  +-- Fortran lib
      +-- debug ($IntDir remains here)
还要将.pdb位置更改为$(OutDir)$(TargetName).pdb。默认值为$(IntDir)vc100.pdb(或visual studio版本的10倍)

2) 重新锁定。无论何时添加断点并运行,pdb文件都将锁定。如果程序未运行,则它们不应锁定,除非您的VS版本已将其锁定。是否已应用VS SP?另外,确保C程序和Fortran程序具有相同的调用约定。有stdcall和cdecl。在Fortran中,这是在项目设置中完成的。如果没有传递任何参数,这无关紧要,但在传递参数时,请确保两者使用相同的约定


有关stdcall和cdecl之间的差异,请参阅

问题中不清楚C代码如何使用Fortran字符串

如果字符串来自C函数:

const char *getcstr(void)
{
    return "Hello!";
}
下面是完整的Fortran程序,它调用C函数,将结果转换为Fortran字符串,然后打印:

implicit none

interface
    function getcstr() bind(c, name="getcstr")
        use, intrinsic :: iso_c_binding
        type(c_ptr) getcstr
    end
end interface

print *, cstr2f(getcstr())

contains
    function cstr2f(s)
        use, intrinsic :: iso_c_binding
        interface
            pure function strlen(s) bind(c, name="strlen")
                use, intrinsic :: iso_c_binding
                type(c_ptr), intent(in) :: s
                integer(c_size_t) strlen
            end
        end interface
        type(c_ptr) s
        character(kind=c_char, len=strlen(s)), pointer :: cstr2f

        call c_f_pointer(s, cstr2f)
    end
end

C代码如何使用Fortran字符串的问题还不清楚

如果字符串来自C函数:

const char *getcstr(void)
{
    return "Hello!";
}
下面是完整的Fortran程序,它调用C函数,将结果转换为Fortran字符串,然后打印:

implicit none

interface
    function getcstr() bind(c, name="getcstr")
        use, intrinsic :: iso_c_binding
        type(c_ptr) getcstr
    end
end interface

print *, cstr2f(getcstr())

contains
    function cstr2f(s)
        use, intrinsic :: iso_c_binding
        interface
            pure function strlen(s) bind(c, name="strlen")
                use, intrinsic :: iso_c_binding
                type(c_ptr), intent(in) :: s
                integer(c_size_t) strlen
            end
        end interface
        type(c_ptr) s
        character(kind=c_char, len=strlen(s)), pointer :: cstr2f

        call c_f_pointer(s, cstr2f)
    end
end

祝你好运我会关注这个问题的答案。祝你好运。“我将关注这个问题的答案。”弗朗西斯卡勒斯感谢您的评论,修改了我的答案。我不知道这与问题的第1点和第2点有什么关系。你是说OP所呈现的代码是错误的吗?以哪种方式?他实际上是在问代码中是否遗漏了什么。是吗?Fortran字符串在Fortran中很有用。OP调用C的转换并放弃结果。@francescalus感谢您的评论,修改了我的答案。我不知道这与问题的第1点和第2点有什么关系。你是说OP所呈现的代码是错误的吗?以哪种方式?他实际上是在问代码中是否遗漏了什么。是吗?Fortran字符串在Fortran中很有用。OP从C调用转换并丢弃结果。