尝试处理 Fortran 指针 - 调用 c_f_pointer
Trying to handle a Fortran pointer - call c_f_pointer
我在使用以下方法后尝试处理 Fortran 指针时遇到问题:
call c_f_pointer(dataPtr, dataF, [natoms,countf])
,其中 dataPtr
是带有 intent(in)
的 C 指针,dataF
是带有 intent(out)
.
的 Fortran 指针
natoms
和 countf
是定义输出指针大小的整数。
变量之前声明为:
use, intrinsic :: iso_c_binding
integer natoms, countf
type(c_ptr) dataPtr
real(c_float), pointer :: dataF(:,:) => NULL()
和dataPtr
来自另一个函数。
如果我打印 shape(dataF)
,我会得到正确的结果。但是我不能用 dataF
打印或复制或做任何事情。我得到的错误是 forrtl: severe (174): SIGSEGV, segmentation fault occurred.
我按照示例 https://software.intel.com/en-us/node/678433 进行了编译和操作,没有任何问题。
编辑:添加更多代码。
program test
use, intrinsic :: iso_c_binding
implicit none
interface
subroutine open(ptr) bind(c, name='open')
use, intrinsic :: iso_c_binding
implicit none
type(c_ptr), intent(out) :: ptr
end subroutine open
subroutine gather(ptr, name, typ, countf, data) bind(c, name='gather')
use, intrinsic :: iso_c_binding
implicit none
type(c_ptr), value, intent(in) :: ptr
type(c_ptr), value, intent(in) :: name
integer(c_int), value, intent(in) :: typ
integer(c_int), value, intent(in) :: countf
type(c_ptr), intent(out) :: data
end subroutine gather
subroutine scatter(ptr, name, typ, countf, data) bind(c, name='scatter')
use, intrinsic :: iso_c_binding
implicit none
type(c_ptr), value, intent(in) :: ptr
type(c_ptr), value, intent(in) :: name
integer(c_int), value, intent(in) :: typ
integer(c_int), value, intent(in) :: countf
type(c_ptr), intent(in) :: data
end subroutine scatter
end interface
integer natoms, countf, typ
character(len=2,kind=c_char) :: var = c_char_'x'//c_null_char
type(c_ptr) ptr, dataPtr
real(c_float), pointer :: dataF(:,:) => NULL()
!opens an instance of the program (loaded as library into my Fortran)
!ptr is a pointer used to reference to it in other calls
call open(ptr)
!Here comes definitions for the integer variables
!...
!get data
call gather(ptr, c_loc(var), typ, countf, dataPtr)
!need to do stuff with the data here
call c_f_pointer(dataPtr, dataF, [natoms,countf])
!return modified data
call scatter(ptr, c_loc(var), typ, countf, dataPtr)
如果我只获取数据 call gather(...)
然后 return 它 call scatter(...)
程序就可以运行。但我需要在两者之间做些事情。
EDIT2:添加了 C 函数
void open(void **ptr) {
// ...
}
void gather(void *ptr, const char *name,
int type, int count, void *data) {
// ...
}
void scatter(void *ptr, const char *name,
int type, int count, void *data) {
// ...
}
看来我明白了。
首先,数据指针必须在子程序 gather
:
中输入为 intent(in)
和 value
subroutine gather(ptr, name, typ, countf, data) bind(c, name='gather')
! ...
type(c_ptr), value, intent(in) :: data
! instead of:
! type(c_ptr), intent(out) :: data
end subroutine gather
我更改了 dataF
的声明,不再需要从 c_f_pointer
调用:
real(c_float), target, allocatable :: dataF(:,:)
所以我删除了 call c_f_pointer(dataPtr, dataF, [natoms,countf])
并添加了:
allocate(dataF(natoms,countf))
dataPtr = c_loc(dataCFloat)
现在,dataF
直接包含更新后的数组。
我在使用以下方法后尝试处理 Fortran 指针时遇到问题:
call c_f_pointer(dataPtr, dataF, [natoms,countf])
,其中 dataPtr
是带有 intent(in)
的 C 指针,dataF
是带有 intent(out)
.
natoms
和 countf
是定义输出指针大小的整数。
变量之前声明为:
use, intrinsic :: iso_c_binding
integer natoms, countf
type(c_ptr) dataPtr
real(c_float), pointer :: dataF(:,:) => NULL()
和dataPtr
来自另一个函数。
如果我打印 shape(dataF)
,我会得到正确的结果。但是我不能用 dataF
打印或复制或做任何事情。我得到的错误是 forrtl: severe (174): SIGSEGV, segmentation fault occurred.
我按照示例 https://software.intel.com/en-us/node/678433 进行了编译和操作,没有任何问题。
编辑:添加更多代码。
program test
use, intrinsic :: iso_c_binding
implicit none
interface
subroutine open(ptr) bind(c, name='open')
use, intrinsic :: iso_c_binding
implicit none
type(c_ptr), intent(out) :: ptr
end subroutine open
subroutine gather(ptr, name, typ, countf, data) bind(c, name='gather')
use, intrinsic :: iso_c_binding
implicit none
type(c_ptr), value, intent(in) :: ptr
type(c_ptr), value, intent(in) :: name
integer(c_int), value, intent(in) :: typ
integer(c_int), value, intent(in) :: countf
type(c_ptr), intent(out) :: data
end subroutine gather
subroutine scatter(ptr, name, typ, countf, data) bind(c, name='scatter')
use, intrinsic :: iso_c_binding
implicit none
type(c_ptr), value, intent(in) :: ptr
type(c_ptr), value, intent(in) :: name
integer(c_int), value, intent(in) :: typ
integer(c_int), value, intent(in) :: countf
type(c_ptr), intent(in) :: data
end subroutine scatter
end interface
integer natoms, countf, typ
character(len=2,kind=c_char) :: var = c_char_'x'//c_null_char
type(c_ptr) ptr, dataPtr
real(c_float), pointer :: dataF(:,:) => NULL()
!opens an instance of the program (loaded as library into my Fortran)
!ptr is a pointer used to reference to it in other calls
call open(ptr)
!Here comes definitions for the integer variables
!...
!get data
call gather(ptr, c_loc(var), typ, countf, dataPtr)
!need to do stuff with the data here
call c_f_pointer(dataPtr, dataF, [natoms,countf])
!return modified data
call scatter(ptr, c_loc(var), typ, countf, dataPtr)
如果我只获取数据 call gather(...)
然后 return 它 call scatter(...)
程序就可以运行。但我需要在两者之间做些事情。
EDIT2:添加了 C 函数
void open(void **ptr) {
// ...
}
void gather(void *ptr, const char *name,
int type, int count, void *data) {
// ...
}
void scatter(void *ptr, const char *name,
int type, int count, void *data) {
// ...
}
看来我明白了。
首先,数据指针必须在子程序 gather
:
intent(in)
和 value
subroutine gather(ptr, name, typ, countf, data) bind(c, name='gather')
! ...
type(c_ptr), value, intent(in) :: data
! instead of:
! type(c_ptr), intent(out) :: data
end subroutine gather
我更改了 dataF
的声明,不再需要从 c_f_pointer
调用:
real(c_float), target, allocatable :: dataF(:,:)
所以我删除了 call c_f_pointer(dataPtr, dataF, [natoms,countf])
并添加了:
allocate(dataF(natoms,countf))
dataPtr = c_loc(dataCFloat)
现在,dataF
直接包含更新后的数组。