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

language interoperability with .NET

nilsoberg
Beginner
585 Views
Hi!

I'm involved in a software project where I need to integrate several Fortran 90/95 models with a C++ modeling framework. The framework uses an extensive class heirarchy to be able to model a variety of scenarios. My question is: Is it possible to provide access to a C++ class and its interface to Fortran through .NET?

Example:

class XYZ
{
//...
virtual void add_to(int x) = 0;
virtual unsigned int size() = 0;
//...
};

class V : public XYZ
{
//...
virtual void add_to(int x);
virtual unsigned int size();
//...
};


void main()
{
XYZ *b = new V();
Results *r1 = CPP_MODEL_AND_MODIFY(b);
Results *r2 = FORTRAN_MODEL(b);
Compare(r1, r2);
}

The CPP_MODEL and FORTRAN_MODEL calls are what I'd like to be able to do. The Fortran code would access some data elements in "b".

Is this possible to do with .NET? Is this possible to do at all?

If so, can someone provide me with a few examples? I see how I can do simple integration with structs, but not with classes.

Thanks!

Nils
0 Kudos
3 Replies
Jugoslav_Dujic
Valued Contributor II
585 Views
I suggest that you don't try direct access, as internal structure of a class is a) complicated b) compiler-dependent, while class member functions are not the same beast as "plain" "C-style" functions.
Instead, you can treat the class object in Fortran as an opaque object (e.g. pointer to "something"), and write plain C-style wrappers for accessing required members from Fortran (primary types or structs). For example:
Code:
class XYZ
{
//...
virtual void add_to(int x) = 0;
virtual unsigned int size() = 0;
//...
};

//C-style wrappers
void XYZadd_to(XYZ& xyz, int x)
{
  xyz.add_to(x);
}

//C-style wrappers
unsigned int XYZsize(XYZ& xyz)
{
  return xyz.size();
}

Fortran code:
! Dummy type
module M_XYZty
type T_XYZ
  integer dummy   !You don't need it, but I'm not sure 
                  !if empty TYPE is allowed
end type T_XYZ
end module M_XYZty
!--------------------
module M_XYZ
use M_XYZty
interface
  subroutine XYZadd_to(xyz, x)
  !DEC$ATTRIBUTES C, DECORATE, ALIAS: "XYZadd_to":: XYZadd_to
  !DEC$ATTRIBUTES REFERENCE:: xyz
  use M_XYZty
  type(T_XYZ):: xyz
  integer::     x
end interface
interface
  integer function XYZsize(xyz)
  ...
end interface

end module M_XYZ
!=====================
subroutine CalledFromC(xyz)
use M_XYZ
call XYZadd_to(xyz, 1)
iSize = XYZsize(xyz)
end subroutine CalledFromC
The idea is that Fortran never ever knows what's the exact format of class XYZ -- all it does is that it receives a reference to it and calls C-stylewrappersto access/manipulate the data.If you want to have a set ofmembers to be accessible from Fortran, it's probably a good idea to pack it in a struct and dedicate a C-style wrapper to provide access to it...
(continued in next post, the Forum has problems with two src sections within one post).
0 Kudos
Jugoslav_Dujic
Valued Contributor II
585 Views
...here it is:
Code:
struct PUBLICDATA {
 ...
}
class XYZ {
  ...
  public
  PUBLICDATA PublicData;

}

void XYZGetPublicData(XYZ& xyz, PUBLICDATA** ppPublicData)
{
  *ppPublicData = &xyz.PublicData;
}

!=============
!In Fortran code, declare T_PUBLICDATA & write the interface:
interface
  subroutine XYZGetPublicData(xyz, pPublicData)
  !DEC$ATTRIBUTES C, ALIAS: ...
  use M_XYZty
  !DEC$ATTRIBUTES REFERENCE:: xyz
  type(T_XYZ):: xyz
  type(T_PUBLICDATA), POINTER:: pPublicData
  end subroutine
end interface

!usage:
subroutine CalledFromC(xyz)
...
type(T_PUBLICDATA), POINTER:: pPD

call XYZGetPublicData(xyz, pPD)

!Now, you obtained the pointer to xyz.pPublicData and you can
!access it directly both for reading (AND writing, which can
!also be a way to shoot yourself in foot):
something = pPD%foo;
pPD%whatever = somethingElse;
end subroutine CalledFromC

Here, I (ab)used the fact that a scalar Fortran POINTER is implemented in CVF/IVF as void*, i.e. a 32-bit address. Thus, implementation of C++ XYZGetPublicData and its Fortran interface are compatible (PUBLICDATA** <-> type(T_PUBLICDATA), POINTER). Don't try this with arrays though.
Jugoslav
0 Kudos
nilsoberg
Beginner
585 Views
Hi Jugoslav!

Thanks a whole bunch - it's very helpful.

Nils
0 Kudos
Reply