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

Passing user defined type pointer between Fortran and C++

Ben136KBC
Novice
719 Views

Hi,

 

I have this Fortran 90 code:

!
! This module contains data for each kbclib instance.
! An instance is passed along during Fortran calls so as
! to support multiple threads calculating at the same time.
!
! Based on http://charm.cs.uiuc.edu/ppl_research/ampi/ampif90.html
!

MODULE SharedData
  TYPE SharedDataChunk

    INTEGER ID
    INTEGER NQTR,QTRLTY(100),QBASIS(100)

  END TYPE
END MODULE

!-------------------------------------------------
!DEC$ ATTRIBUTES STDCALL :: getshareddataid

INTEGER FUNCTION getshareddataid(sharedDataInstance)
  USE SharedData
  TYPE(SharedDataChunk), pointer :: sharedDataInstance
  INTEGER id

  id = sharedDataInstance%ID
  getshareddataid = id

END FUNCTION

!-------------------------------------------------
!DEC$ ATTRIBUTES STDCALL :: CreateSharedData

FUNCTION CreateSharedData(id) result(res)
  USE SharedData
  INTEGER id

  TYPE(SharedDataChunk), pointer :: res

   INTERFACE
     integer function getshareddataid(sharedDataInstance)
!DEC$ ATTRIBUTES STDCALL :: getshareddataid
       USE SharedData
       TYPE(SharedDataChunk), pointer :: sharedDataInstance
     end FUNCTION
   END INTERFACE

! Create an instance

  TYPE(SharedDataChunk), pointer :: c
  ALLOCATE(c)

! Now do any initialization

  c%id = 2
  c%ID = id

  id = getshareddataid(c)

! Return a pointer to it.

  res = c

END FUNCTION

And this Visual C++ code:

extern "C"
   {
   void* __stdcall createshareddata(long id);
   long __stdcall getshareddataid(void*);
   }

void Test()
   {
   long id = 1;
   void* instData = createshareddata(id);
   long id2 = getshareddataid(instData);
   }

 

0 Kudos
5 Replies
Ben136KBC
Novice
718 Views

The problems are as follows:

  1. When it enters createshareddata, id has a value of 32 instead of the expected value of 1.
  2. If you skip over that line, it crashes on the line: res = c

This is pretty much all of the code. Save the Fortran to a F90 file, the C++ to a C++ file (or just the snippet into a main C++ file). 

0 Kudos
Ben136KBC
Novice
718 Views

I am trying to declare a user defined data type, hang onto instances of it in the C++ world, and pass one of those instances as an argument when calling Fortran routines. From all I have read, that should be possible, but I cannot make it work. I am using these compilers:

 

Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 19.0.5.281 Build 20190815

Microsoft (R) C/C++ Optimizing Compiler Version 19.29.30038.1 for x64

 

Please help! Lionel?

0 Kudos
Ben136KBC
Novice
690 Views

I am guessing that Intel Fortran stores pointers as something more than what C++ does. I guess one idea would be to keep only the integer id on the C++ side and then pass that into Fortran which can locate the matching instance and then pass that in to other Fortran calls?

0 Kudos
FortranFan
Honored Contributor II
678 Views

@Ben136KBC ,

 

See this thread where I show the other way around i.e., define a class in C++, "hang onto instances of it in the" Fortran world, and "pass one of those instances as an argument when calling" C++ functions that are decorated as extern "C":  The example uses standard Fortran interoperabilty features.

https://community.intel.com/t5/Intel-Fortran-Compiler/Calling-C-cpp-objects-from-a-Fortran-subroutine/m-p/1110557/highlight/true#M129102

You can follow the same code design pattern for the situation of interest you. 

0 Kudos
Steve_Lionel
Honored Contributor III
682 Views

Fortran pointers are not interoperable with C pointers. There is the C_PTR derived type, with which you can use C_F_POINTER and C_LOC. DO not use integers to store pointers.

0 Kudos
Reply