我认为头衔说我需要什么。我知道我们可以使用“asd”函数来执行此操作,但由于某些原因,我需要在Fortran中进行分配(即在子例程“asd_”中)。这是C代码:
#include <stdio.h>
void asd(float **c) {
*c = (float *) malloc (2*sizeof(float));
**c =123;
*(*c+1)=1234;
}
void asd_(float **c);
main () {
float *c;
asd_(&c);
// asd(&c); would do the job perfectly
printf("%f %f \n",c[0],c[1]);
return 0;
}
这是Fortran代码:
subroutine asd(c)
implicit none
real, pointer, allocatable ::c(:)
print *, associated(c)
if(.not. associated(c)) allocate(c(2))
end subroutine
这随机给出了分段错误。任何帮助将不胜感激。
答案 0 :(得分:10)
Fortran 2003 ISO C Binding提供了一种可移植的方法。它在许多编译器中实现。这是示例代码。
#include <stdio.h>
void test_mem_alloc ( float ** array );
int main ( void ) {
float * array;
test_mem_alloc (&array);
printf ( "Values are: %f %f\n", array [0], array [1] );
return 0;
}
和
subroutine test_mem_alloc ( c_array_ptr ) bind (C, name="test_mem_alloc")
use, intrinsic :: iso_c_binding
implicit none
type (c_ptr), intent (out) :: c_array_ptr
real (c_float), allocatable, dimension (:), target, save :: FortArray
allocate (FortArray (1:2) )
FortArray = [ 2.5_c_float, 4.4_c_float ]
c_array_ptr = c_loc (FortArray)
end subroutine test_mem_alloc
答案 1 :(得分:1)
如果您想使用Fortran内部类型,这也是另一种解决方案。这是我的情况,因为我需要使用预先指定的数据类型从外部库调用例程。这基本上是使用包装器Fortran子例程完成的。这是C代码:
void mywrap_(void **);
void myprint_(void *);
main () {
void *d;
mywrap_(&d);
myprint_(d);
return 0;
}
这是包装器:
subroutine mywrap(b)
implicit none
include "h.h"
type(st), target, save :: a
integer, pointer :: b
interface
subroutine alloc(a)
include "h.h"
type(st) a
end subroutine alloc
end interface
call alloc(a)
b => a%i
end
Fortran代码:
subroutine alloc(a)
implicit none
include "h.h"
type(st) a
a%i = 2
a%r = 1.5
if (allocated(a%s)) deallocate(a%s)
allocate(a%s(2))
a%s(1) = 1.23
a%s(2) = 1234
end
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
subroutine myprint(a)
implicit none
include "h.h"
type(st) a
print *,"INT: ", a%i
print *,"REAL: ", a%r
print *,"ALLOC: ", a%s
end
头文件“h.h”:
type st
sequence
integer i
real r
real, allocatable :: s(:)
end type
注意,这样C中的所有对象都是不透明的。
答案 2 :(得分:1)
如果您需要线程安全的解决方案和/或再次从C释放空间的可能性,下面的示例将完成这项工作:
#include <stdio.h>
void test_mem_alloc(float ** array, void **wrapper);
void free_wrapper(void **wrapper);
int main()
{
float *array;
void *wrapper;
/* Allocates space in Fortran. */
test_mem_alloc(&array, &wrapper);
printf( "Values are: %f %f\n", array [0], array [1]);
/* Deallocates space allocated in Fortran */
free_wrapper(&wrapper);
return 0;
}
在Fortran端,您有一个通用的包装器类型CWrapper
,它可以携带任何类型的派生类型。后者包含您想要传递的数据。 CWrapper
类型接受任意有效负载,您总是从C调用free_wrapper()
例程来释放内存。
module memalloc
use, intrinsic :: iso_c_binding
implicit none
type :: CWrapper
class(*), allocatable :: data
end type CWrapper
type :: CfloatArray
real(c_float), allocatable :: array(:)
end type CfloatArray
contains
subroutine test_mem_alloc(c_array_ptr, wrapper_ptr)&
& bind(C, name="test_mem_alloc")
type (c_ptr), intent (out) :: c_array_ptr
type(c_ptr), intent(out) :: wrapper_ptr
type(CWrapper), pointer :: wrapper
allocate(wrapper)
allocate(CfloatArray :: wrapper%data)
select type (data => wrapper%data)
type is (CfloatArray)
allocate(data%array(2))
data%array(:) = [2.5_c_float, 4.4_c_float]
c_array_ptr = c_loc(data%array)
end select
wrapper_ptr = c_loc(wrapper)
end subroutine test_mem_alloc
subroutine free_cwrapper(wrapper_ptr) bind(C, name='free_wrapper')
type(c_ptr), intent(inout) :: wrapper_ptr
type(CWrapper), pointer :: wrapper
call c_f_pointer(wrapper_ptr, wrapper)
deallocate(wrapper)
end subroutine free_cwrapper
end module memalloc