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!

SETTING 2DARRY INPUT ARGUMENT OF A C++ PROCEDURE CALLABLE FROM FORTRAN

Status
Not open for further replies.

alorenzom

Technical User
Jun 15, 2007
6
FI
I must write a C++ procedure callable from Fortran
which set 2D array input argument.I have written a version in Fortran and I get correct results.I have written my c++ procedure and I get a terrible outcome: in particular If I print array values, they are correct, but subsequently run is completed with some unexpected warnings results aren't correct.I suppose there's a problem of "dialogue" between my "talking in C++" and what machine understands.

My fortran subroutine that works fine (simplified at max and in pseudocode ) is:

Code:
      SUBROUTINE UEL(AMATRX,NDOFEL) 
C 
      DIMENSION AMATRX(NDOFEL,NDOFEL) 
C 
      AMATRX(1,1) = 11 
      AMATRX(1,2) = 12 
      .... etc ..... 
C 
      RETURN 
      END

PLEASE HELP ME.IT COULD BE VERY USEFUL FOR MY WORK.
ANY SUGGESTION IS WELCOME.THANKS IN ADVANCE


 
Please don't type everything in capitals - it is like shouting and you really don't need to shout.

Your question is very OS/Compiler dependent. Before anyone can answer your question, they would need to know

1) which C++ compiler (eg WatCom)
2) which Fortran compiler (eg gfortran)
3) which version of Fortran (eg 77, 2003)
4) which OS (eg Windows)
 
Thamk you so much and sorry I don't want shout (it has been due to caps lock!)

I must do a simulation with Abaqus/standard, analysis code by Simulia, which has a user subroutine interface in fortran(and you can write user subroutine in fortran or in other programming language).Abaqus standard link the .obj obtained by compiling my c++ procedure and call it to do some calculations of some 2D array.The final solution of the simulation isn't correct, while the final solution of the simulation using a fortran version of my procedure is correct.(I must use C++ for my procedure!)

I'm using:

Visual C++ 7.1

Intel Fortran Compiler 9.1 (but because my evaluation copy will expire, probably I'll change in 8.1 or later)

Windows XP x86-32

I use a macro so my c++ procedure is callable from fortran.Here is what I would write in c++ to do what I write in fortran in previous posted message

Code:
#ifndef FOR_C_H
#define FOR_C_H
#define FOR_NAME(lc_name,uc_name) _stdcall uc_name
#define CALL_NAME(lc_name,uc_name) uc_name
#endif
extern "C" void
FOR_NAME(uel, UEL)(double **amatrx,int * ndofel)
{
   amatrx = new double*[*ndofel];
   for(int i=0; i<*ndofel; i++)
       amatrx[i] = new double[*ndofel];
   amatrx[1][1] = 11;
   amatrx[1][2] = 12;
   ...
    
}

Using print instruction, I know values of my 2D array calculated with c++ procedure and fortran subroutine are the same.

So I think it's a problem of "PASSING VALUES"


 
If you're using visual C++ (Microsoft), declare the Fortran routines as PASCAL. i.e.
Code:
extern pascal void ...
If you look at the code generation, you will notice the difference: a C routine will push parameters into the stack, call the routine and pop them off. A pascal routine will push them into the stack but the return statement in the routine pops them off.

Fortran assumes contiguous storage so allocate your array as a 1D array. i.e.
Code:
amatrx = new double*[ndofel];
amatrx[0] = new double[(*ndofel)*(*ndofel)];
for (int i = 1; i < *ndoel; i++)
   amatrx[i] = &amatrx[0][i * (*ndoel))];
 

Hi,alorenzom

The following has worked for me (Using Microsoft Fortran):

Define the interface in the Fortran program (for either a function or a subroutine), for instance:

INTERFACE TO SUBROUTINE CSUBR [C] (I2)
INTEGER*2 I2 [NEAR,REFERENCE]
END

INTERFACE TO FUNCTION CFUNC [C] (I2,S1,S2,T1)
INTEGER*2 CFUNC
INTEGER*2 I2
INTEGER*2 S1 [NEAR,REFERENCE]
INTEGER*2 S2
CHARACTER*(*) T1 [NEAR,REFERENCE]
END

and then:

integer*2 hWnd
integer*2 status
integer*2 S1,S2
character*64 T1,T2,T3

call CSUBR(hWnd)
status = CFUNC(hWnd,S1,S2,T1)


The C-routines were:
------------------------------------------
void csubr(hWnd)
int near *hWnd;
{
char line[64] = "\0";
char stre[64] = "\0";
int status = 0;
strcpy(lina,"C_Subr\0");
strcpy(stre,"Message\0");
status = MessageBox(*hWnd,stre,line,MB_OK);
}
------------------------------------------
int cfunc(hWnd,I1,I2,T1)
int hWnd;
int near *I1;
int I2;
char near T1[64];
{
char line[64] = "\0";
char stre[64] = "\0";
int status = 0;
int result = 1;
strcpy(line,"C_Func\0");
strcpy(stre,"Message\0");
status = MessageBox(hWnd,stre,line,MB_OK);
*I1 = 555;
I2 = (int)666;
strcpy(T1,"777\0");
return(result);
}
------------------------------------------
 
Thank you so much to everyone.
I solved my problem.
After some changes, now my abaqus analysis job with c++ user subroutine get the same results of my abaqus analysis job with fortran user subroutine.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top