Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Visual C++ shared access with Intel Fortran module

Status
Not open for further replies.

josey1

Programmer
Nov 25, 2008
4
US
I want to know how to access the data in a Fortran 90 Module from Visual C++. I am using Visual C++ .net 2003 and Intel Fortran 10.1. I added the fortran .lib file to the linker inputs in visual c++. My program compiles no problem, but then has an access violation error upon running.

Code:
C++ header file foo.h

#pragma pack(2)
extern "C" char name[30];

extern "C" struct{
    int forTyp_mp_x,
    float forTyp_mp_y,
    int forTyp_mp_z,
    float forTyp_mp_ARR[100][10];
}fortType;
#pragma pack()

extern "C" void USEFORTMOD();

class foo
{
    test();
     ~test();
    init();

}


C++ foo.cpp file

#include <foo.h>

void init()
{
    forTyp_mp_x = 5;
    forTyp_mp_y = 3.3;
    ...
    forTyp_mp_arr2(1) = 1.5;

     USEFORTMOD();
}


Fortran module file fort_mod.for

module fortmodule

character*30 name

pointer x
pointer y
pointer z
pointer arr(:,:)
pointer arr2(:)

type forTyp
    integer x
    real y
    integer z
    real arr(:,:)
    real arr2(:)
end type forTyp

type(forTyp), pointer:: ptr2typ0 


Fortran useFortmod.for

subroutine useFortmod()

use fortmodule;
allocatable arr2(:)

 do i=1,x
      z=arr2(i)+ z
      write(*,*)'z= ',z
 enddo

end

The values in the fortran code are always zero. I would like for the "C++ values" to used/modified by the Fortran code and then be able to used the new values in C++.

Any help is greatly appreciated.
 
First I would suggest you write some really simple examples, say just a shared int, and crawl through the code an instruction at a time using a debugger.
Just to see what it going on.

Mixed language development is hard enough when both compilers are from the same vendor. Your arrangement is going to be that much harder.

For example, your struct in Fortran code has two arrays, and the C one has only one array.

Also, there are many unexplained variables in your Fortran code.


--
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
 
I don't know if 10.1 is the same as 7.1. On 7.1, click on

Intel Software Development Tools->
Intel Fortran Compiler->
Documentation Index

In the HTML page that pops up, select Intel Fortran Compiler User's Guide. This may create a .chm file. Open the .chm file.

You will see a list of topics, amongst them Mixing C and Fortran and passing pointers.


 
Thank you both for responding. You are right I did forget to add the other array in my .cpp. I was trying not to cut/paste too much.

Salem, I have done what you said and so far so good. I am going to work my way up to the code that I need.

xwb, yes I did find the documentation and I will use and let you know how it goes.
 
Hi, I am back again. I am still having a problem. So I am going to explain what I am trying to do, then post the code I have, and maybe get some help.

I want my C++ program to set some variable that are in an area that can be shared with Intel Fortran 10.1. I then want to call a Fortran subroutine to access these variables, do some calculations with said variables, and set results in the same shared data area. Then I expect C++ to be able to access the results and print.

I can pass arguments command line to fortran no prob, but am trying to take my skills up a notch by using the Module feature.


So far this works fine for basics types ( thank you Salem), but when I make my own derived type in the Fortran module and call the Fortran module, the values in the Fortran subroutine are always zero.


Code:
C++ .h file

typedef struct {
    int ITEST;
    float RTEST;
    float result;
} TESTER;

extern "C" 
void callFortran();

Class Test
{
    public:
        TESTER cstruct;

     Test();
     ~Test();

     void croutine();

}


C .cpp file

void croutine()
{
    cstruct.ITEST = 333;
    cstruct.RTEST = 4.4;
    cstruct.result = 0.0;

    callFortran();

    printf("result is %lf\n", cstruct.result);

}



[COLOR=blue]

Fortran .mod

      module test 
      
        use, intrinsic :: ISO_C_BINDING
          save
!     testing 123...
        type, BIND(C) :: MYTYPE 
          
            integer(C_INT) :: itest
            real(C_FLOAT) :: rtest
            real(C_FLOAT) :: resulttest
        end type MYTYPE
          
        type(MYTYPE), BIND(C) :: tester
       
      end module test


Fortran .f


Subroutine callFortan()

      use test

!     added write statements just to see if values were
!     correct
      write(*,*)'itest = ', tester%itest
      write(*,*)'rtest = ', tester%rtest
      write(*,*)'resulttest = ', tester%resulttest

      tester%resulttest = tester%rtest * tester%rtest

 !    call more Fortran subroutine to do more stuff

      return
end
[/Color]

I may be incorrectly accessing the Module test in the fortran subroutine ( tester%itest???).
Again any help is appreciated
 
I think I would start with the other direction (Fortran to C), but that's because I only know how to do the clever bit in C :)

In Fortran, assign values to members of the struct.

In C, I would do
Code:
unsigned char *mem = &cstruct;
for ( i = 0 ; i < sizeof(cstruct) ; i++ ) {
  printf( "%02x ", mem[i] );
}
printf( "\n" );

You could also do
[tt]memset( &cstruct, 0x55, sizeof(cstruct) );[/tt]
before calling the Fortran code.
Any 0x55 you see in the dump would indicate "holes" in the structure (as seen by Fortran), which your C equivalent would need to take account of.


--
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
 
Okay, I have been messing around and have figured out a little bit more. C++ and Fortran can access/share memory for most basic types and basic derived types. I have fixed the example I diplayed earlier so that it works.
HOWEVER, I still don't seem to be able to get any array to be shared as well. At best, I can set an array with values on the C++ side, and Fortran seems to be receiving the address, but not the values of the array. Fortran does pass by reference, but isn't there some way to get the values that were set in the C++ code???

Here is the fixed code from above. I will add the array stuff in red since is doesn't work. Code seems to work w/o stuff in red.

[Code/]
C++ .h file

typedef struct {
int ITEST;
float RTEST;
float result;

int arr[9];

} MYTYPE;

extern "C" MYTYPE *TEST_mp_TESTER;

extern "C"
void callFortran();

Class Test
{
public:

Test();
~Test();

void croutine();

}


C .cpp file

void croutine()
{
TEST_mp_TESTER = new MYTYPE;

TEST_mp_TESTER.ITEST = 333;
TEST_mp_TESTER.RTEST = 4.4;
TEST_mp_TESTER.result = 0.0;


//put some values in array


for (int k = 0; k < 10; k++)
TEST_mp_TESTER->atest[k] = k * 10;


callFortran();

printf("result is %lf\n", TEST_mp_TESTER.result);

}





Fortran .mod

module test
save

! testing 123...
type,public :: MYTYPE

integer :: itest
real :: rtest
real :: resulttest


integer, allocatable :: array:))

end type MYTYPE

type(MYTYPE), pointer :: tester

end module test


Fortran .f


Subroutine callFortan()

use test

! added write statements just to see if values were
! correct

write(*,*)'itest = ', tester%itest
write(*,*)'rtest = ', tester%rtest
write(*,*)'resulttest = ', tester%resulttest

tester%resulttest = tester%rtest * tester%rtest


write(*,*)'array(1) =', tester%array(1)

! call more Fortran subroutine to do more stuff

return
end
[/Code]



Oh, and I also called a Fortran subroutine prior to the croutine to allocate space for the array, but I get access violation errors. As always any help is much apprecaited.

 
Well since the Fortran says "allocatable", the nearest equivalent I can think of would be something like
Code:
typedef struct {
    int ITEST;
    float RTEST;
    float result;
[red]    int *arr;[/red]
} MYTYPE;

However, what Fortran must also be storing somewhere is a sense of how big the array is at the moment, and perhaps how big it could be before it needs to reallocate it.

It might be a simple pointer (as above)

It might be like this
Code:
typedef struct {
    int ITEST;
    float RTEST;
    float result;
[red]    int maxsize;
    int *arr;[/red]
} MYTYPE;

It might be like this even
Code:
typedef struct {
    int ITEST;
    float RTEST;
    float result;
[red]    dynarray *arr;[/red]
} MYTYPE;
Where dynarray is yet another structure which holds all the Fortran array "admin" data, as well as a pointer to the actual data.

If you fill the array with 0 to 9, then memory which looks like
[tt]00 00 00 00 01 00 00 00 02 00 00 00 00 03 00 00 00 00[/tt]
etc, is probably your atual array.
If it's like [tt]xx yy 00 00[/tt], then that could be a size.
Anything else which is 4 non-zero bytes is probably an address. Put that address into the memory watch window of the debugger, and see where it leads you.



--
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top