应该如何多的Fortran字符串传递到C? [英] How should multiple Fortran strings be passed to C?

查看:403
本文介绍了应该如何多的Fortran字符串传递到C?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

要传递一个Fortran字符串到C,一个隐藏的参数也通过与变量的大小。这里有一个工作FORTRAN定义和C(实际上是C ++ / CLI)方法:

To pass a Fortran string to C, a hidden parameter is also passed with the variable's size. Here's a working fortran definition, and the C (actually C++/CLI) method:

  interface
     subroutine AppendExtension(
 +      Filename)
 +      bind(C, name="AppendExtension")
     character *1, intent(inout):: Filename
    end subroutine AppendExtension
  end interface

和这里的C ++ / CLI被调用:

and here's the C++/CLI that gets called:

extern "C" {
  void __declspec(dllexport) __cdecl AppendExtension(
                                         char * name, 
                                         int buffersize)
{
  String^ clistr = gcnew String(name);
  clistr = System::IO::Path::ChangeExtension(clistr->Trim(), gcnew String("OUT"));
  IntPtr p = Marshal::StringToHGlobalAnsi(clistr);
  char *pNewCharStr = static_cast<char*>(p.ToPointer());
  int cstrlen = strlen(pNewCharStr);
  memcpy_s(name, buffersize, pNewCharStr, cstrlen);
  if (cstrlen < buffersize)
  {
    // backfill with spaces, since a Fortran string is spaces on the right.
    memset(&name[cstrlen], ' ', buffersize-cstrlen);
  }
  Marshal::FreeHGlobal(p);
}

以上正常工作(英特尔视觉的Fortran 2013 SP1)。

The above is working properly (Intel Visual Fortran 2013 SP1).

我现在想两个字符串传递到一个函数。下面是我所做的:

I now want to pass two strings into a function. Here's what I did:

   interface
     subroutine ParseSpec(
 +      Filename, Corename)
 +      bind(C, name="ParseSpec")
     character *1, intent(inout):: Filename
     character *1, intent(inout):: Corename
    end subroutine ParseSpec
   end interface

下面是在行动召唤:

      CHARACTER*80 FILE_SPEC
      CHARACTER*200 CORE_NAME
      CALL ParseSpec(FILE_SPEC, CORE_NAME)

和这里的C ++ / CLI:

and here's the C++/CLI:

void __declspec(dllexport) __cdecl ParseSpec(char * name, char * corename, int namelen, int corelen)
{
  // namelen and corelen both contain the length of "name".
  ...

有两个隐藏变量。我觉得他们应该是buffersizes每个我的两个字符串,一为文件名,一个是Corename的。但两者都包含第一缓冲区的缓冲区的大小,即80。

There are two hidden variables. I think they should be for the buffersizes for each of my two strings, one for "Filename" and one for "Corename". But both contain the buffer size of the first buffer, namely 80.

我在哪里去了?

推荐答案

有关BIND(C)过程的调用约定可以从一个Fortran编译使用Fortran的与Fortran调用默认调用约定大不相同。你不应该依赖任何隐藏的字符长度参数(在一般情况下,你也应该想到的是,隐藏参数的数据类型的 INT )。我怀疑你刚才是幸运的,因为该Fortran的CHARACTER变量是由编译器在内存布局方式。

The calling convention for BIND(C) procedures can be quite different from the default calling convention that a Fortran compiler uses for Fortran to Fortran calls. You should not rely on any hidden CHARACTER length arguments (in the general case, you also shouldn't expect that the hidden arguments are of type int). I suspect you have just been lucky, given the way that the Fortran CHARACTER variable is laid out in memory by that compiler.

有没有必要编译器将一个BIND(C)过程的长短,因为变量可互操作的用C字符的长度只有一个。然而,如果伪参数是一个数组(这是你想要什么,如果你正在传递一个字符串,而不是单个字符),即数组的大小可能是非负 - 的Fortran序协会的规则KIND = C_CHAR字符意味着可以标量与数组相关联。

There is no need for the compiler to pass the length for a BIND(C) procedure, because the only length of a CHARACTER variable interoperable with C is one. However, if the dummy argument is an array (which is what you want if you are passing a string, rather than an individual character), the SIZE of that array may be non-negative - the rules of Fortran sequence association for KIND=C_CHAR character mean you can associate a scalar with an array.

所有了 - 改变Fortran函数的声明使得字符的参数是数组,并添加参数明确地传递这些数组长度

All up - change the Fortran function declaration such that the character arguments are arrays and add arguments to explicitly pass the length of those arrays.

使用游离形式的源,并假定缺省字符相同C_CHAR种类:

Using free form source, and assuming that default character is the same as C_CHAR kind:

interface
  subroutine ParseSpec(  &
        Name, Name_len,  &
        Corename, Corename_len )  &
      bind(C, name="ParseSpec")
    use, intrinsic :: iso_c_binding, only: c_int, c_char
    integer(c_int), value :: Name_len
    character(kind=c_char), intent(inout) :: Name(Name_len)
    integer(c_int), value :: Corename_len
    character(kind=c_char), intent(inout):: Corename(Corename_len)
  end subroutine ParseSpec
end interface

USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_INT
CHARACTER*80 FILE_SPEC
CHARACTER*200 CORE_NAME
CALL ParseSpec(  &
    FILE_SPEC, LEN(FILE_SPEC, KIND=C_INT),  &
    CORE_NAME, LEN(CORE_NAME, KIND=C_INT) )

extern "C" void ParseSpec( 
    char* name, int name_len, 
    char* corename, int corelen );
// Operations on name[0] to name[name_len-1] and 
// corename[0] through corename[core_len-1]...

这篇关于应该如何多的Fortran字符串传递到C?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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