Как передать массив строк C (char* cstrings[]
) в подпрограмму Fortran?
Вопрос Массивы строк в мостах fortran-C с использованием iso_c_binding определенно связан с , но ответ кажется неправильным и даже не компилируется с GNU Fortran.
В настоящее время я работаю над интерфейсом C для кода Fortran, и я ожидал, что iso_c_binding
(который я использовал ранее) сделает это проще простого. Пока не повезло с массивами строк C ...
Подпрограмма Fortran должна принимать в качестве аргумента массив строк. На простом Фортране я бы написал примерно следующее:
subroutine print_fstring_array(fstring)
implicit none
character(len=*), dimension(:), intent(in) :: fstring
integer :: i
do i = 1, size(fstring)
write(*,*) trim(fstring(i))
end do
end subroutine print_fstring_array
Один из способов передать одну строку C в Фортран - это указатель C (c_ptr
) (я знаю, я мог бы также использовать массив character(kind=c_char)
)
subroutine print_cstring(cstring) bind(C)
use iso_c_binding, only: c_ptr, c_f_pointer, c_loc, c_null_char
implicit none
type(c_ptr), target, intent(in) :: cstring
character(len=1024), pointer :: fstring
integer :: slen
call c_f_pointer(c_loc(cstring), fstring)
slen = index(fstring, c_null_char) - 1
write(*,*) fstring(1:slen)
end subroutine print_cstring
Итак, я предположил, что массив c_ptr
будет хорошей идеей
subroutine print_cstring_array(n, cstring) bind(C)
use iso_c_binding, only: c_ptr, c_int, c_f_pointer, c_loc, c_null_char
implicit none
integer(kind=c_int), intent(in) :: n
type(c_ptr), dimension(n), target, intent(in) :: cstring
character(len=1024), pointer :: fstr
integer :: slen, i
do i = 1, n
call c_f_pointer(c_loc(cstring(i)), fstring)
slen = index(fstring, c_null_char) - 1
write(*,*) fstring(1:slen)
end do
end subroutine print_cstring_array
но это приводит к ошибке сегментации.
Код C для последнего примера:
# include "stdio.h"
# include "fstring.h"
void main(void) {
char* cstring[] = { "abc", "def", "ghi", "jkl" };
int n = 4;
print_cstring_array(&n, cstring);
}
а содержимое файла заголовка fstring.h
просто:
void print_cstring_array(int* n, char* cstring[]);
Я нацелен на GNU Fortran и Intel Fortran и протестировал вышеперечисленное с GNU Fortran. Длина строк фиксирована (3 в приведенном выше примере), на случай, если это упростит решение. Однако размер массива может быть разным.
Приветствуются любые указатели (даже указатели C).
char* cstrings[]
- это массив указателя на строки, он не обязательно относится к непрерывному блоку памяти. Посмотрите здесь: stackoverflow.com/q/13869528/694576 и обратите внимание на разницу в том, как определяется массив строк. - person alk   schedule 01.09.2014c_f_pointer(cptr, fptr[, shape])
принимает форму массива в качестве необязательного третьего аргумента (найденного в ответе, на который вы указали). Вы можете опубликовать это в качестве ответа. В противном случае я сделаю это сам, так как считаю, что это полезно для других людей и не идентично связанному вопросу. - person alexurba   schedule 01.09.2014alk
я решил проблему. - person alexurba   schedule 01.09.2014