经过大量搜索后,我发现我认为最接近问题的答案是在Fortran接口上的Stack Overflow(SO)上,以调用返回指针的C函数(已发布将近10年前!)。
我引用这是因为使用该示例可使代码保持简单,并且仍然说明了我的问题。
我想返回一个已经在C ++中创建/分配的内存的数组,并且能够在Fortran中分析答案,因为这是此应用程序的大部分代码所在的地方。我的应用程序进入C ++生成整数数组答案,并通过C接口将其返回给Fortran程序。原始的SO示例使用单个双精度变量作为返回值。我将其更改为整数,因为这就是我在应用程序中要处理的内容。示例代码(已更改)有效。
我已在注释中突出显示了为返回数组指针而试图进行的更改,但是我已经没有足够的想法了。(我可以说,“哦,在糟糕的过去,我可以将整数等同于iarray(1)并超出数组的大小。”但我不会。拥有编码保护是很好的,但是有时令人沮丧。)
我正在使用Visual Studio 2017和Intel Fortran parallel_studio_xe_2019_update5_composer。
我对原始SO代码的修改示例:
! ps_test_pointers.f90
program foo
use, intrinsic :: iso_c_binding, only : c_ptr, &
c_f_pointer, &
c_int
implicit none
type(c_ptr) :: c_p!(:) ! <-------
integer(c_int), pointer :: f_p!(:) ! <-------
interface
function foofunc() bind(c)
import :: c_ptr
implicit none
type(c_ptr) :: foofunc!(:) ! <-------
end function foofunc
end interface
c_p = foofunc()
call c_f_pointer(c_p, f_p)
print *, f_p
end program foo
// ps_test_pointersC.cpp : 'Subroutine' only.
extern "C" {
int bar[3] = { 2, 3, 4 };
int *foofunc() {
return bar;
}
}
就像我在上面说的那样,代码可以正常工作,因为它可以打印出数组的第一个元素(“ 2”)。
如果我在f_p的定义中添加'(:)',代码将正确编译,但是当我运行它时,程序将失败,并显示运行时错误:“ Forrtl:严重(408):Fort:(7) :尝试在“调用c_f_pointer(c_p,f_p)”行使用未与目标关联的指针F_P。
我尝试将c_p声明为数组(“ c_p(:)”),但在同一位置却遇到相同的错误。
我还尝试过将c_p用作子例程的参数–仍然仅使用整数:
! ps_test_pointers.f90
program foo
use, intrinsic :: iso_c_binding, only : c_ptr, &
c_f_pointer, &
c_int
implicit none
type(c_ptr) :: c_p!(:) ! <-------
integer(c_int), pointer :: f_p!(:) ! <-------
interface
subroutine foofunc(c_p) bind(c)
import :: c_ptr
implicit none
type(c_ptr) :: c_p!(:) ! <-------
end subroutine foofunc
end interface
call foofunc(c_p)
call c_f_pointer(c_p, f_p)
print *, f_p
end program foo
// ps_test_pointersC.cpp : 'Subroutine' only.
extern "C" {
int bar[3] = { 2, 3, 4 };
void foofunc(int *rtn) {
rtn = bar;
}
}
但是C函数中创建的指针永远不会在返回时分配给c_p(因此永远不会定义f_p)。
阅读这个问题,我希望我不处于编译器实现的前沿,并且在限制加紧但不能应付所有用例之间暴露出一个问题!
有针对这个的解决方法吗?
关于子例程方法,我认为我们可能需要在C / C ++端声明c_p
为int**
(而不是int*
),以获取bar
via参数关联的地址(而不是函数返回值)。所以像...
main.f90:
program foo
use, intrinsic :: iso_c_binding, only : c_ptr, &
c_f_pointer, &
c_int
implicit none
type(c_ptr) :: c_p
integer(c_int), pointer :: f_p(:)
integer(c_int) :: nsize
interface
subroutine foosub( c_p, nsize ) bind(c)
import :: c_ptr, c_int
implicit none
type(c_ptr) :: c_p !<-- sends the pointer to c_p
integer(c_int) :: nsize !<-- sends the pointer to nsize
end subroutine
end interface
call foosub( c_p, nsize )
call c_f_pointer( c_p, f_p, [nsize] )
print *, "nsize = ", nsize
print *, "f_p(:) = ", f_p(:)
end program
sub.cpp:
extern "C" {
int bar[3] = { 2, 3, 4 };
void foosub( int** rtn, int* nsize ) {
*rtn = bar;
*nsize = sizeof(bar) / sizeof(int);
}
}
编译并运行:
$ g++-10 -c sub.cpp
$ gfortran-10 -c main.f90
$ g++-10 main.o sub.o -lgfortran
$ ./a.out
nsize = 3
f_p(:) = 2 3 4
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句