我遵循以下示例(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 ++?
答案 0 :(得分:1)
首先,你不能在Fortran和C之间的接口上使用std::string
。std::string
是一些C ++实现定义的对象,它没有保证内存布局以便与Fortran互操作。
您必须使用纯C字符串。因此,CVLiDAR__new()
必须接受char*
类型的参数,并且fortran接口必须将此参数声明为
character(kind = c_char) :: name(*)
Fortran包装程序必须使用一些Fortran character
伪参数,然后将其内容复制到一个适当分配的character(kind = c_char)
数组中,然后传递给C函数。
此时,您的C接口函数可能会继续将其转换为C ++ std::string
。这种转换是可选的,因为C ++可以像C一样处理C字符串。但是,添加转换将允许其余代码更纯粹的C ++。
在Fortran端组装时,不要忘记正确终止带有零字符的C字符串!
这些参数转换确实是PITA,如果您需要从Fortran调用任意数量的接口函数,建议编写生成Fortran包装器的生成器脚本。可以在文件cdi-1.8.1/interfaces/f2003/bindGen.rb
中的气候数据接口库(CDI,源代码可以在https://code.mpimet.mpg.de/projects/cdi/files找到)中找到此类脚本的示例,其输出也在同一版本中发布cdi-1.8.1/src/mo_cdi.f90
下的焦油球。对于您的案例,此脚本可能完全过度,但对于CDI而言,它可以正常运行,其输出可能会激发/帮助您了解如何正确进行转换。
答案 1 :(得分:0)
您无法从Fortran传递C ++ string
(实际上是std::string
)。它与C或Fortran完全不兼容,它是一种内部C ++类型。您必须使用C包装器并传递C兼容的字符数组。