通过动态分配的字符串从C到Fortran
我正在尝试将动态分配的字符串阵列( char *** str
)从C到Fortran,但是在删除Fortran中的C指针时,我似乎缺少某些内容,从而产生垃圾字符串作为输出(请参见下面的MWE)。
附带问题
正在调用 DealLocate(FPTR)
足以阻止下面的程序泄漏内存(我认为不会)?如果没有,可以从fortran中释放 msgs
(在c)中?
为了复制
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void str_alloc(char*** msgs, size_t * n) {
*n = 3;
int str_len = 10;
(*msgs) = malloc(*n * sizeof(char*));
for (int i = 0; i < *n; i++) {
(*msgs)[i] = malloc((str_len + 1) * sizeof(char));
strcpy((*msgs)[i], "012346789");
}
}
program main
use iso_c_binding
implicit none
interface
subroutine str_alloc(msgs, n) bind(C, name="str_alloc")
use iso_c_binding
type(c_ptr), intent(out) :: msgs
integer(c_size_t), intent(out) :: n
end subroutine
end interface
integer, parameter :: STRLEN = 10
character(kind=c_char, len=STRLEN), allocatable :: names(:)
call str_array_from_c(names)
contains
subroutine str_array_from_c(strs)
character(len=STRLEN), allocatable, intent(out) :: strs(:)
type(c_ptr) :: cptr
integer(c_size_t) :: i, n, lenstr
character(kind=c_char, len=1), pointer :: fptr(:,:)
call str_alloc(cptr, n)
call c_f_pointer(cptr, fptr, [int(STRLEN, kind=c_size_t), n])
allocate(strs(n))
print*, "Output C-str array from fortran"
do i = 1_c_size_t, n
lenstr = cstrlen(fptr(:, i))
strs(i) = transfer(fptr(1:lenstr,i), strs(i))
print*, fptr(1:STRLEN, i), "|", strs(i)
end do
deallocate(fptr)
end subroutine str_array_from_c
!> Calculates the length of a C string.
function cstrlen(carray) result(res)
character(kind=c_char, len=1), intent(in) :: carray(:)
integer :: res
integer :: i
do i = 1, size(carray)
if (carray(i) == c_null_char) then
res = i - 1
return
end if
end do
res = i
end function cstrlen
end program main
编译
gcc -c -g -Wall -o cfile.o cfile.c
gfortran -g -Wall -o main.o cfile.o main.f90
输出
Output C-str array from fortran
0�P�|0�
p�|
!|
其他信息
- ,我无法编辑C接口。
- C
str_len
实际上是可变的,因此字符串的数组被锯齿状。据我所知,唯一没有定义自定义类型的解决方案是使用足够大的len =
字符的字符。 - 我相对确信,我的错误是我如何在检查
cptr
的十六进制以来,说明字符串存在
相关帖子
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在C侧,您有一系列指针,这与二维的fortran阵列不同。 Fortran没有“指针数组”概念,因此您必须具有带有指针组件的派生类型数组。
首先,从C代码返回的CPTR必须转换为派生类型的数组,其每个元素都包含指向字符串的指针。然后,您将遍历每个中的每一个,将子组件C_PTR转换为Fortran指针,然后是您的字符数组。
其次,您不能
DealLocate
Fortran没有分配的东西。您将不得不回到C中以释放这些字符串。这是有效的Fortran代码的修订版。 C代码没有更改。
当我构建并运行这个时,我会得到:
On the C side you have an array of pointers, which is NOT the same as a two-dimensional Fortran array. Fortran doesn't have the "array of pointers" concept, so you have to have an array of derived type with a pointer component.
First, the cptr returned from the C code has to be converted to an array of the derived type, each element of which contains a pointer to the string. You then iterate through each of these, converting the subcomponent C_PTR to a Fortran pointer, which is then your array of characters.
Second, you can't
DEALLOCATE
something that Fortran didn't allocate. You would have to call back into C to free those strings.Here is a revised version of your Fortran code that works. The C code didn't change.
When I build and run this I get: