Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
Welcome to the Intel Community. If you get an answer you like, please mark it as an Accepted Solution to help others. Thank you!

2D character array with Bind-C

abhimodak
New Contributor I
71 Views

Hi 

This is one of those often-asked question and my apologies in advance for not doing an exhaustive search. 

The C-snippet is:

#include <stdio.h>

void Display2D(int iLen, int jNum, char ** string) {

int j, k;
for (j= 0; j < jNum; j = j+1){
for (k = 0; k < iLen; k=k+1){
   printf("%c", string);
   } 
   printf("\n");
   }
}

And Fortran is trying to use it as:

      Program Test
         
         Use ISO_C_BINDING
         
         Implicit None
         
         Interface
            Subroutine Display2D(iLen, iSize, String) Bind(C, Name='Display2D')
               Import
               Integer(C_INT), VALUE :: iLen, iSize
               Character(C_CHAR) :: String(iLen,iSize)
            End Subroutine Display2D
         End Interface

         Character(C_CHAR) :: STR(3,2)

         STR(1:3,1) = ['O','M', C_NULL_CHAR]
         STR(1:3,2) = ['S','H', C_NULL_CHAR]
         Call Display2D(Size(STR,dim=1), Size(STR,dim=2), STR)
         
      End Program Test 

But this doesn't work. Is it supposed by the inter-operability in F2003?

Abhijit

 

0 Kudos
2 Replies
abhimodak
New Contributor I
71 Views

I guess I should be looking at C_PTR....

Abhi

JVanB
Valued Contributor II
71 Views

Yep, your interfaces are inconsistent. You either have to change the C side to use C99 VLAs (which might not be available in MSVC++)

#include <stdio.h>

void Display2D(int iLen, int jNum, char string[jNum][iLen])
{
   int j, k;
   for(j = 0; j < jNum; j++)
   {
      for(k = 0; k < iLen; k++)
      {
         printf("%c", string);
      }
      printf("\n");
   }
}
Program Test
   use ISO_C_BINDING
   implicit none
   interface
      subroutine Display2D(iLen, jNum, string) bind(C,name='Display2D')
         import
         implicit none
         integer(C_INT), value :: iLen, jNum
         character(KIND=C_CHAR) string(iLen, jNum)
      end subroutine Display2D
   end interface
   character(KIND=C_CHAR) STR(3,2)
   STR = reshape(['O','M',C_NULL_CHAR, &
                  'S','H',C_NULL_CHAR],shape(STR))
   Call Display2d(size(STR,1),size(STR,2),STR)
End Program Test

Or change the Fortran to pass an array of C_PTR:

#include <stdio.h>

void Display2D(int iLen, int jNum, char **string)
{
   int j, k;
   for(j = 0; j < jNum; j++)
   {
      for(k = 0; k < iLen; k++)
      {
         printf("%c", string);
      }
      printf("\n");
   }
}
Program Test
   use ISO_C_BINDING
   implicit none
   interface
      subroutine Display2D(iLen, jNum, string) bind(C,name='Display2D')
         import
         implicit none
         integer(C_INT), value :: iLen, jNum
         type(C_PTR) string(jNum)
      end subroutine Display2D
   end interface
   character(KIND=C_CHAR), target :: STR(3,2)
   type(C_PTR), allocatable :: pSTR(:)
   integer i
   STR = reshape(['O','M',C_NULL_CHAR, &
                  'S','H',C_NULL_CHAR],shape(STR))
   allocate(pSTR(size(STR,2)))
   do i = 1, size(pSTR)
      pSTR(i) = C_LOC(STR(1,i))
   end do
   Call Display2d(size(STR,1),size(STR,2),pSTR)
End Program Test

Either way works in gcc/gfortran, with output

OM
SH

 

Reply