从Fortran返回字符串到C ++ [英] Return string from Fortran to C++

查看:158
本文介绍了从Fortran返回字符串到C ++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在C ++中调用以下函数:

  int strLength = 20; 
char * name;

getName(name,strLength);

printf(name:%s\\\
,name);

在Fortran中:

  subroutine getName(name)bind(c,name ='GETNAME')
use,intrinsic :: iso_c_binding
隐式无
字符,意图(out)::名称

name ='Martin'
结束子程序getName

当我执行C ++例程时,输出是: name:M 。现在,我想这是因为字符,intent(out):: name 声明了大小为1的名称变量,但如果我将声明更改为: character(len = 6),intent(out):: name 我得到以下错误消息: Error :(1)处的字符参数'name'必须是长度1,因为过程'getname'是BIND(C)。我也尝试过:字符(len = 6,kind = c_char),intent(out):: name ,并带有相同的错误信息。最后,我试过了这样一个声明: character(c_char),dimension(6),intent(out):: name ,它会编译但得到如下结果: name:MMMMMM



我的问题归结为:如何从Fortran返回一个字符串到C ++?

解决方案

这个基于Fortran函数的方法非常整齐,并且非常适用于尚未设置字符串的情况(或者为其分配了内存)在C例程中。请注意,您无需传入字符串长度参数,也可以使用假定大小的数组来构建/返回字符串值。 1



Fortran可分配的字符串常量被使用,所以这个函数可以被任何字符串重用。

一个整数参数也传递到Fortran函数中,例如,说明如何指示期望的响应应该是什么。



请注意,在这个例子中,intent(out)用于表示整数参数在传递之前不需要被定义,但它可能是在返回之前更新。因此,您可以修改其值并将其返回给调用程序,以便它可以用作返回代码。



Fortran函数

 ! f_string.f90 
!从C例程调用:`myString = get_string(rc)`

函数get_string(c_rc)bind(c,name ='get_string')
use,intrinsic :: iso_c_binding
隐式无
整数(c_int),意图(out):: c_rc! < - 通过参考传递;在这个例子中用作返回码。
type(c_ptr):: get_string! < - C_PTR传递回C
字符(len = :),allocatable,target,save :: fortstring! < - Allocatable /任何长度都没问题

fortstring =将C_NULL_CHAR添加到任何Fortran字符串常量中。// C_NULL_CHAR
get_string = c_loc(fortstring)! < - C_LOC内在函数获取我们的字符串的loc。
c_rc = 1! <设置返回码值。
结束函数get_string

C程序

  // c_string.c 
#include
#include< string.h>
#include< stdlib.h>

char * get_string(int * rc); //< - Fortran函数签名。

int main(){
int rc; //< - 没有设定值。
char * mynameptr; //< - 只是普通的ol'char *,不需要内存分配。

mynameptr = get_string(& rc);

printf(mynameptr =%s\,mynameptr);
printf(len =%d\\\
,strlen(mynameptr));
printf(rc =%d\\\
,rc);
return rc;

编译,调用,输出:

  ifort / c f_string.f90 
icl c_string.c / link f_string.obj
c_string.exe
#示例输出:
#mynameptr =将C_NULL_CHAR附加到任何Fortran字符串常量。
#len = 48
#rc = 1

1 这也可以在没有警告的情况下进行干净编译(使用 OP的解决方案没有我在其评论中提出的修改)。


I have the following function call in C++:

int strLength = 20;
char* name;

getName(name, strLength);

printf("name: %s\n", name);

and in Fortran:

subroutine getName(name) bind (c, name='GETNAME')
use,intrinsic :: iso_c_binding
implicit none
character, intent(out) :: name

name = 'Martin'
end subroutine getName

When I execute the C++ routine the output is: name: M. Now, I suppose this happens because character, intent(out) :: name declares the name variable with size of 1, but if I change the declaration to this: character(len=6), intent(out) :: name I get this error message: Error: Character argument 'name' at (1) must be length 1 because procedure 'getname' is BIND(C). I've also tried this: character(len=6,kind=c_char), intent(out) :: name, with the same error message. Lastly, I tried this declaration: character(c_char),dimension(6), intent(out) :: name, which compiles but, yields this result: name: MMMMMM.

My question boils down to: How can I return a string from Fortran to C++?

解决方案

This Fortran function-based approach is neat and tidy, and is quite suitable when the string has not yet been set (or had memory allocated for it) in the C routine. Notice that you do not need to pass in a string length argument, or use an assumed-size array to build/return a string value.1

A Fortran allocatable character string constant is used, so that this function is reusable for any string.

An integer argument is also passed into the Fortran function to demonstrate, for example, how you may indicate what the desired response should be.

Notice that in this example "intent(out)" is used to indicate that the integer argument does not need to be defined before being passed in, but that it may be updated before it is returned. Therefore, you can modify its value and return it to the calling program so that it may instead be used as a "return code".

The Fortran Function

! f_string.f90
! Called from C routine as:  `myString = get_string(rc)`

function get_string(c_rc) bind(c, name='get_string')
    use, intrinsic :: iso_c_binding
    implicit none
    integer(c_int), intent(out) :: c_rc           ! <- Pass by reference; acts as return code in this example.
    type(c_ptr) :: get_string                     ! <- C_PTR to pass back to C
    character(len=:), allocatable, target, save :: fortstring   ! <- Allocatable/any length is fine

    fortstring = "Append C_NULL_CHAR to any Fortran string constant."//C_NULL_CHAR
    get_string = c_loc(fortstring)                ! <- C_LOC intrinsic gets loc of our string.
    c_rc = 1                                      ! <- Set the return code value.
end function get_string

The C Program

// c_string.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char *get_string(int *rc);              // <- The Fortran function signature.

int main(){
    int rc;                             // <- No value set.
    char *mynameptr;                    // <- Just a plain ol' char *, no memory allocation needed.

    mynameptr = get_string(&rc);

    printf("mynameptr=%s\n", mynameptr);
    printf("len =%d\n", strlen(mynameptr));
    printf("rc  =%d\n", rc);
    return rc;
}

Compile, call, output:

ifort /c f_string.f90
icl c_string.c /link f_string.obj
c_string.exe
# example output: 
# mynameptr=Append C_NULL_CHAR to any Fortran string constant.
# len =48
# rc  =1

1 This also compiles cleanly without warnings (which do occur with the OP's solution without the modifications I suggested in its comments).

这篇关于从Fortran返回字符串到C ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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