Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
New Contributor I

2D character array with Bind-C

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
Highlighted
New Contributor I

I guess I should be looking

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

Abhi

0 Kudos
Highlighted
Valued Contributor II

Yep, your interfaces are

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

 

0 Kudos