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

How to allocate a Fortran dynamic array in a dynamic-linked library written in C++?

Port__Phillip
Beginner
861 Views


Hello,

I'm trying to allocate a Fortran dynamic array in a member function of
a dynamic-linked library written in C.
The compiling and linking is success, but the exacution afterwards has
some problems.
It get stuck at the "new" sentance in the dynamic-linked library member function.

The C++ codes (secso.cpp) for dynamic-linked library:

#include <iostream>
extern "C"
{
    int f( double ** array)
    {
        int j,k;

        std::cout << "The allocation 1"<<std::endl;
        array[0] = new double [9*3];
        std::cout << "The allocation 2"<<std::endl;
        for (j=0;j<9;j++)
        {
            for (k=0;k<3;k++)
            {
                array[0] [j*3+k] = double((j+1)*10+k+1);
            }
        }

        return 0;
    }
}

The Fortran main function code (test.f90):

program test
implicit none

real(kind=8),  pointer :: array(:,:)

! External C style function
call f(array)

write (*,*) array
deallocate (array)

end program test

 

Make file (makefile):

SHELL = /bin/bash
test:
 icpc -shared -fPIC -o libsec.so secso.cpp
 ifort -assume nounderscore -o test.exe test.f90 -L. -lsec

What should I do?
Any advise would be helpful, thanks in advance.

0 Kudos
6 Replies
mecej4
Honored Contributor III
861 Views

To some extent, what your code does is similar to two persons writing checks on a single account without either being aware of what the other person is doing. Having Fortran de-allocate memory that was allocated in C, or vice versa, is sure to cause trouble. The following modification of your code works on Windows 32-bit (but it is a quick-and-dirty fix-up, which you should sanitize and adapt for Linux symbol naming conventions, and consistently use only ISO-C-Interoperability methods or only "legacy" methods):

File csub.cpp:

#include <iostream>
extern "C"
{
    int F( double ** array)
    {
        int j,k;

        std::cout << "The allocation 1"<<std::endl;
        array[0] = new double [9*3];
        std::cout << "The allocation 2"<<std::endl;
        for (j=0;j<9;j++)
        {
            for (k=0;k<3;k++)
            {
                array[0] [j*3+k] = double((j+1)*10+k+1);
            }
        }

        return 0;
    }
}

extern "C"{
void C_FREE(void **p){
   free(*p);
   }
}

File fmain.f90:

program test
use, intrinsic :: iso_c_binding
implicit none

real(kind=8),  pointer :: array(:,:)
type(C_PTR) :: cptr_to_array

! External C style function
call f(cptr_to_array)
call C_F_POINTER (cptr_to_array, array, [3,9])

write (*,*) array
call c_free (cptr_to_array)

end program test

 

0 Kudos
Steven_L_Intel1
Employee
861 Views

I would recommend using the extended C interoperability features from draft Fortran 2015, supported in the 16.0 compiler. I'll work up a version of your code done this way.

0 Kudos
Steven_L_Intel1
Employee
861 Views

This isn't your program, but it illustrates how to pass deferred-shape and allocatable arrays from Fortran to C and to have the C code do the allocation.

#include "ISO_Fortran_binding.h"
extern int c_alloc (CFI_cdesc_t * descr) {
	int ret, i;
	float * array;
	CFI_index_t lower = 0, upper = 10;
	ret = CFI_allocate (descr, &lower, &upper, 0); // No elem_len
	if (ret == CFI_SUCCESS) {
		array = descr->base_addr;
		for (i=lower;i<=upper;i++) {
			array = (float) i;
		}
	}
	return ret;
}
use, intrinsic :: iso_c_binding
interface
  function c_alloc (array) bind(C)
  import
  integer(C_INT) :: c_alloc
  real(C_FLOAT), intent(out), allocatable, dimension(:) :: array
  end function c_alloc
end interface

real(C_FLOAT), allocatable, dimension(:) :: my_array
if (c_alloc(my_array) == 0) then
  print *, lbound(my_array), ubound(my_array); print *, my_array
  end if
end

 

0 Kudos
Port__Phillip
Beginner
861 Views

Thank Mr. Lionel and Mr(s) mecej4 for your time and kind reply.

The codes really help me a lot.

My fortran codes now could processing arrays from C style shared library.

Is there any tutorials about shared libraries for beginners like me?

 

0 Kudos
Steven_L_Intel1
Employee
861 Views

The Intel Fortran documentation has topics on shared libraries. https://software.intel.com/en-us/node/579667 is a current (16.0) documentation link - if that link doesn't work in the future, look under Compiler Reference > Libraries > Creating Shared Libraries.

0 Kudos
Adel_S_
Beginner
861 Views

thank you mr. Steve for reply 

0 Kudos
Reply