Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

move_alloc pointer array to allocatable array

Patrice_l_
Beginner
608 Views

Hi,

Is there a way to move the data from a pointer to an allocatable without doing a copy ?

The data is allocated in C, but used and deallocated in fortran in a dimension(:),pointer, but then it needs to be attached to a class, but i dont see a way of moving the data to the allocatable without a copy.

 

Thanks.

Pat.

0 Kudos
5 Replies
Steven_L_Intel1
Employee
609 Views

No, you can't do this. And I hope you aren't using Fortran DEALLOCATE to deallocate storage allocated in C. You can convert a C pointer to a Fortran pointer (which you aren't allowed to deallocate), but ALLOCATABLEs are in their own realm. Polymorphism is another barrier here - even with the new C descriptor support in 16.0, you can't make polymorphic objects interoperable with C.

0 Kudos
Patrice_l_
Beginner
609 Views

Just to have clear idea on what i am talking about here is a sample code below. I understand for a structure it is complicated but for a basic type , as long as i keep track of all my allocation and I am sure this pointer is not referenced anywhere else i should be ok ?

#include <stdlib.h>
#include <stdio.h>
int* alloc(int n)
{
	int i;
	int *p=malloc(sizeof(int)*n);

	printf("allocate int array size %d\n",n);


	for (i=0;i<n;i++){
		p=i; 
		printf("p %d = %d\n",i,p);
	}
	return p;

}

and

 

program foo
use iso_c_binding
type(c_ptr) :: c_array
integer ,dimension(:),pointer ::fc_array 
integer ,dimension(:),allocatable :: array 
integer :: n

interface
type(c_ptr) function alloc(n) bind(c)
use iso_c_binding
integer(c_int),value :: n
end function
end interface

n=20

c_array=alloc(n)
call c_f_pointer(c_array,fc_array,(/n/))

print *,fc_array


!move fc_array storage to fc_array ??
allocate(array(n))
array=fc_array

deallocate(array)

! Forbidden ???? but working ?
deallocate(fc_array)

end program foo

 

0 Kudos
Steven_L_Intel1
Employee
609 Views

That last deallocate is indeed forbidden. That it seems to "work" is an accident, and it could corrupt memory. Don't do it. But you can now (in 16.0) do this:

#include "ISO_Fortran_binding.h"
#include <stdio.h>
#include <stdlib.h>

extern "C" int alloc(CFI_cdesc_t * dv, int n) {
    CFI_index_t lower[1], upper[1];
    int i, ret;
    int* p;

    lower[0] = 1;
    upper[0] = n;

    ret = CFI_allocate(dv, lower, upper, 0);
    if (ret == CFI_SUCCESS) {
        printf("allocate int array size %d\n", n);
         p = (int *) dv->base_addr;

        for (i = 0; i < n; i++){
            p = i;
            printf("p %d = %d\n", i, p);
        }
    }
    return ret;
}
program foo
use iso_c_binding
 
integer(c_int) ,dimension(:),allocatable :: array 
integer(c_int) :: n, ret

interface
integer(c_int) function alloc(array,n) bind(c)
import
integer(c_int), dimension(:), allocatable :: array
integer(c_int), value :: n
end function
end interface

n=20

ret = alloc(array,n)
print *,array


deallocate(array)

end program foo

 

Still can't make in polymorphic, though.

0 Kudos
Patrice_l_
Beginner
609 Views

I am not worry about polymorphic at all, and since the library design in C does not depend on me, all i  have is a C wrapper and i could  use it to assign the base_addr ,CFI_ssetpointer ?

I will do some more test and get familiar with the new CFI functions.

Thanks.

0 Kudos
Steven_L_Intel1
Employee
609 Views

The way you'd have to do this with CFI_setpointer is to create a separate C descriptor with CFI_establish, that points to malloced storage, and then use CFI_setpointer to do the pointer assign. It would then be not allowed to deallocate it in Fortran nor could you make this an allocatable.

You aren't allowed to modify the base_addr component yourself.

0 Kudos
Reply