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

MIXED LANGUAGE: C++ calling fortran sharing module and common data

bmchenry
New Contributor II
1,020 Views

I can get the C_Calling_Fortran Sample working. no problem.

so to keep the issue simple, itry to createa module anda common to'share' data between the C++ and fortranprograms, it compiles & links fine, but no sharing. (global items in C++ undefined on debug browse)

I've tried uppercase, lowercase, mentalcase! underscore, before/after/etc.

Could someone give me a hint as towhat i'm doing wrong?

thank you.

[bash]cmain.cpp
#include 
#include 
#include "test1.h"

#ifdef __cplusplus
extern "C" 
#endif

#ifdef USEDLL
__declspec(dllimport)
#endif

void FSUB 
                     (int *INT_ARG,
                      char *STR_IN,
                      char *STR_OUT,
                      size_t STR_IN_LEN,
                      size_t STR_OUT_LEN);

void main (int argc, char *argv[])
{
char instring[40];
char outstring[40];
int intarg;

strcpy_s(instring,"Testing...");
intarg = 123;
/* Call Fortran routine - pass intarg by reference,
pass length of outstring explicitly */
FSUB(&intarg,instring,outstring,strlen(instring),sizeof(outstring));

printf(" %f %i %i %f %i %i", EXAMP.A, EXAMP.I1, EXAMP.I2, COMMON_EXAMP.AA, COMMON_EXAMP.II1, COMMON_EXAMP.II2);
EXAMP.A = 0.;
EXAMP.I1 = 0.;
EXAMP.I2 = 0.;
COMMON_EXAMP.AA = 0.;
COMMON_EXAMP.II1 = 0.;
COMMON_EXAMP.II2 = 0.;
printf(" %f %i %i %f %i %i", EXAMP.A, EXAMP.I1, EXAMP.I2, COMMON_EXAMP.AA, COMMON_EXAMP.II1, COMMON_EXAMP.II2);
printf("%s\n",outstring);
} 

file test1.h
extern "C" 
{
struct EXAMP
{
float A;
int  I1;
int  I2;
} EXAMP;

struct COMMON_EXAMP
{
  float AA;
  int II1;
  int II2;
 } COMMON_EXAMP;
}

file fsub.f90
MODULE EXAMP
IMPLICIT NONE
SAVE
   REAL(4)    :: A
   INTEGER(4) :: I1
   integer(4) :: I2
END MODULE EXAMP
SUBROUTINE FSUB (INT_ARG, STR_IN, STR_OUT)
use examp
IMPLICIT NONE
SAVE
  REAL(4) AA
  INTEGER(4) :: II1, II2
  COMMON / COMMON_EXAMP / AA,II1,II2
!DEC$ ATTRIBUTES DLLEXPORT :: FSUB
INTEGER, INTENT(IN) :: INT_ARG
CHARACTER(*), INTENT(IN) :: STR_IN
CHARACTER(*), INTENT(OUT) :: STR_OUT
CHARACTER*5 INT_STR
WRITE (INT_STR,'(I5.5)')INT_ARG
A  = 12.
I1 = 22
I2 = 33
AA  = 13.
II1 = 24
II2 = 34
STR_OUT = STR_IN // INT_STR // CHAR(0)
RETURN
END [/bash]
[bash]

and the command lines (for quick check) for fortran compile

/nologo /debug:full /Od /names:uppercase /module:"Debug/" /object:"Debug/" /traceback /check:bounds /libs:dll /threads /dbglibs /c

fortran link

/OUT:"..\USEDLL/FDLL.dll" /INCREMENTAL:NO /NOLOGO /MANIFEST /MANIFESTFILE:"C:\Source09\misc\mixedlanguage\C_calls_Fortran\USEDLL\FDLL.dll.intermediate.manifest" /DEBUG /PDB:"..\USEDLL/FDLL.pdb" /SUBSYSTEM:WINDOWS /IMPLIB:"..\USEDLL/FDLL.lib" /DLL

c++ compile:

/Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "USEDLL" /D "_VC80_UPGRADE=0x0710" /D "_MBCS" /Gm /EHsc /RTC1 /MDd /Fo"Debug\\" /Fd"Debug\vc90.pdb" /W3 /nologo /c /Wp64 /ZI /TP /errorReport:prompt

C++link

/OUT:"Debug/USEDLL.exe" /INCREMENTAL /NOLOGO /MANIFEST /MANIFESTFILE:"Debug\USEDLL.exe.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"Debug/USEDLL.pdb" /SUBSYSTEM:CONSOLE /DYNAMICBASE:NO /MACHINE:X86 /ERRORREPORT:PROMPT fdll.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib

[/bash]
0 Kudos
3 Replies
Steven_L_Intel1
Employee
1,020 Views

I don't think you can use extern "C" the way you did - in any case it doesn't work. If you put extern "C" before each struct, it does. Or look at my revised version which uses C interoperability features. (It isn't a full-on C interop example, though, which would require some changes to the way character arguments are handled.)

0 Kudos
Lorri_M_Intel
Employee
1,020 Views

I know that the nicest thing to do would be to take your program, edit it, and repost it, but I don't really have the time to do that :-(

Couple of things; Just because the module is named "examp" does not mean there exists a struct-like entity named "examp". Moduleshave data*plus* derived type declarations, interface declarations, etc. Moreover, the data is individually declared, and may or may not be declared in the same order you wrote them. In your C program, you're only referencing your own copy of the struct examp.

Now the COMMON block *does* havea struct-like entity (in a very loose way of course) however, you have not exported its name from the DLL.

Thetool I use when I'm trying to reconcile names between C and Fortran is the linker. That is, I would issue the command:

link -dump -symbols fsub.obj (( or fsub.lib after your DLL has been built ))

and look for the name Fortran created. You can, of course, use the same link command on the C object and then work towards reconciliation.

Finally, please take a peek at the mixed language program chapters in the online documentation for more help. You might also want to research the iso_c_binding module to further help with C interoperability; this gives the bonus of being standard too.

- Lorri

0 Kudos
bmchenry
New Contributor II
1,020 Views

Steve, Lorri,

Thank you both for the prompt responses. I will tinker and see which works best.

The main thing i'm looking into is data sharing betwen C++ and Fortran rather than passing arguments. I started with the C_Calling_Fortran example and tried to expand on it to see if a module share and a common share could be added and what's strength/weakness of each. The documentation sometimes gives conflicting/confusing/it was too late to be absorbingrecommendations/techniques.

Once i resolve I'lladd a project to the thread with a working copy/sample project with both types of shares (modules and common)

burned a wee bit too much midnight oil last night spinning my wheels!

Thanks again!

Brian

0 Kudos
Reply