Problem with C++ dll being used in FORTRAN - Programmers Heaven

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories

Problem with C++ dll being used in FORTRAN

Hi,
I am stuck at a point where I am using mixed language programming of C++ and FORTRAN. I have a C++ function in a dll which returns a pointer. I tried to call it from my FORTRAN program. I have no problem in compiling, linking and running. However, after the run I get the C pointer returned as 0. It is not a problem with the function in the dl because I have checked with the dll being called from both C++ and C# programs. So I think it is something to dow ith FORTRAN calling the C++ function. Here is the structure of the program:

[code]// C++ Header
// ---------------
# include statements
#ifdef BUILD_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
// #define DLL_EXPORT __declspec(dllimport)
#endif

//#ifdef __cplusplus
extern "C"
{
double DLL_EXPORT __cdecl *CalcAirProperties(int InputCombination, double Input1, double Input2, double Pressure);
}
// ---------------
//C++ source code
// ---------------
double DLL_EXPORT __cdecl *CalcAirProperties(int InputCombination, double Input1, double Input2, double Pressure)
{
double *AirProperties = new double[7];
//Do Calculations
return AirProperties
}
// ---------------[/code]

Here is my FORTRAN code:

[code]!********************
PROGRAM ProgramMain
USE Statements
USE iso_c_binding, ONLY : c_ptr,c_double,c_f_pointer
IMPLICIT NONE
TYPE(c_ptr) :: c_p
REAL(c_double), POINTER :: f_p(:)
INTERFACE

FUNCTION CalcAirProperties(InputComb, InpValue1,InpValue2,BarometricPressure) BIND(C,NAME='CalcAirProperties')

USE ISO_C_BINDING

INTEGER(kind=C_INT), INTENT(IN) :: InputComb
REAL(kind=C_DOUBLE), INTENT(IN) :: InpValue1
REAL(kind=C_DOUBLE), INTENT(IN) :: InpValue2
REAL(kind=C_DOUBLE), INTENT(IN) :: BarometricPressure

TYPE(c_ptr) :: CalcAirProperties
END FUNCTION

END INTERFACE
REAL :: TempDB_Test
REAL :: TempRH_Test
REAL :: BaroPressure

TempDB_Test = 308.15
TempRH_Test = 0.69
BaroPressure = 101.325

c_p = CalcAirProperties(2,TempDB_Test,TempRH_Test,BaroPressure)

CALL c_f_pointer(c_p,f_p,[7])

RHiC = f_p(3)
RhoAiC = f_p(7)
END ProgramMain
!********************[/code]

In the above set up the pointer returned by the c_p=CalcAirProperties() call is 0 and thus the values f_p is not pointing to the right array start.
So to remove all the problems with pointers I converted the C++ function to accept an array (by reference) so that I can set the desired array values inside the C++ function and thus pass the array back to FORTRAN. Here is what I did for that:

[code]// C++ Header
// ---------------
# include statements
#ifdef BUILD_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
// #define DLL_EXPORT __declspec(dllimport)
#endif

//#ifdef __cplusplus
extern "C"
{
void DLL_EXPORT __cdecl CalcAirProperties(int InputCombination, double Input1, double Input2, double Pressure,double PropertyArray[]);
}
// ---------------
//C++ source code
// ---------------
void DLL_EXPORT __cdecl CalcAirProperties(int InputCombination, double Input1, double Input2, double Pressure,double PropertyArray[])
{
double *AirProperties = new double[7];
//Do Calculations
for(int i =0;i<7;i++)
{
PropertyArray(i) = AirProperties(i);
}
}
// ---------------[/code]

Here is my FORTRAN code:
[code]!********************
PROGRAM ProgramMain
USE Statements
USE iso_c_binding, ONLY : c_ptr,c_double,c_f_pointer
IMPLICIT NONE
TYPE(c_ptr) :: c_p
REAL(c_double), POINTER :: f_p(:)
INTERFACE

SUBROUTINE CalcAirProperties(InputComb, InpValue1,InpValue2,BarometricPressure,PropertyArray) BIND(C,NAME='CalcAirProperties')

USE ISO_C_BINDING

INTEGER(kind=C_INT), INTENT(IN) :: InputComb
REAL(kind=C_DOUBLE), INTENT(IN) :: InpValue1
REAL(kind=C_DOUBLE), INTENT(IN) :: InpValue2
REAL(kind=C_DOUBLE), INTENT(IN) :: BarometricPressure

REAL(kind=C_DOUBLE), DIMENSION(7), INTENT(OUT) :: PropertyArray
END SUBROUTINE

END INTERFACE
REAL :: TempDB_Test
REAL :: TempRH_Test
REAL :: BaroPressure
REAL(kind=C_DOUBLE), DIMENSION(7) :: PropertyArray
TempDB_Test = 308.15
TempRH_Test = 0.69
BaroPressure = 101.325

CALL CalcAirProperties(2,TempDB_Test,TempRH_Test,BaroPressure,PropertyArray)

RHiC = PropertyArray(3)
RhoAiC = PropertyArray(7)

END ProgramMain
!********************[/code]
The above method also did not work. So I am kind of lost. I am still a newbie when it comes to mixed language programming.

I am using gcc with Code::Blocks to create the C++ dll and gfortran with Simply Fortran IDE to create the fortran exe.

I would appreciate any help in this regards.

Regards
SNKP
Sign In or Register to comment.