Calling C Procedures Directly (GFortran Only)
Calling C Procedures through a Fortran Interface Routine
It is possible to interface to C language source, so long as the source is defined as a procedure (or procedures) within an external file – either a C source file (*.c) or precompiled object (*.obj) file. C source cannot be inserted directly into the Fortran, DSDYN or DSOUT segments, as these are reserved for Fortran only.
When using the GFortran compiler, C procedures may be called directly from within the Fortran, DSDYN, or DSOUT segments of a component definition, although this is not recommended (see Calling C Procedures Directly (GFortran Only) below for reasons why). Preferably, users should instead call a special Fortran interface routine (sometimes referred to as a ‘wrapper’), which will in turn call the C procedure.
Prior to compilation of the project, ensure that any source (*.c) files are referenced in the Additional Source Files project setting (under the Fortran tab). Alternatively, object files (*.obj) or a library file (*.lib) should be referenced in the Additional Library (*.lib) and Object (*.obj) Files project setting (under the Link tab).
For more details on interfacing to C source code, see the example projects in the ...\Examples\CInterface directory within your installation directory.
Note that mechanisms are provided in the Component Wizard, which can automatically create C language interface for you. See Component Wizard Pane for more details.
As mentioned above, in many instances it is perfectly all right to call C procedures directly from the Fortran, DSDYN or DSOUT segments. This, for the most part, is true for simple procedures that do not require advanced EMTDC intrinsic variables.
When compiling the Fortran code for a module, PSCAD includes only a standard set of EMTDC header files. A snippet of a typical Fortran file is shown below, which illustrates the header files that are included:
!--------------------------------------- ! Standard includes !---------------------------------------
INCLUDE 'nd.h' INCLUDE 'emtconst.h' INCLUDE 'emtstor.h' INCLUDE 's0.h' INCLUDE 's1.h' INCLUDE 's2.h' INCLUDE 's4.h' INCLUDE 'branches.h' INCLUDE 'pscadv3.h' INCLUDE 'fnames.h' INCLUDE 'radiolinks.h' INCLUDE 'matlab.h' INCLUDE 'rtconfig.h'
|
If your C procedure requires variables from EMTDC header files other than those shown above, then you cannot call the procedure directly from the Fortran, DSDYN or DSOUT segments. You must create a Fortran interface routine that includes the required header files before the procedure is called (next section).
See Include Files for descriptions of the available header files.
EXAMPLE 9-14:
A user has written the following simple subroutine in C, and wants to call this source code directly from a user-defined component:
/* User C Source Code */ void test_csub_(int* arg, int* res) { *res = 6*(*arg); }
|
A standard call statement can be made from within the Fortran, DSDYN or DSOUT segments of the component definition.
CALL TEST_CSUB($IN,$OUT)
|
Where $IN and $OUT are input and output port connections on the component respectively.
EXAMPLE 9-15:
A user has written the following simple function in C, and wants to use this source code in a user-defined component:
/* User C Source Code */ int test_cfun_(int *arg) { return 2*(*arg); }
|
The function must be declared before it is used within the component. Then, the function is used as it normally would in Fortran in the Fortran, DSDYN or DSOUT segments of the component definition.
#FUNCTION INTEGER TEST_CFUN $OUT = TEST_CFUN($IN)
|
Where $IN and $OUT are input and output port connections on the component respectively.
If you are using one of the supported commercial Fortran compilers, you must call your C procedures through an interface subroutine. These compilers require that you construct an INTERFACE statement to describe your C procedure. See the following section for details.
It is good coding practice that an auxiliary Fortran subroutine be provided for the purpose of interfacing to C functions and procedures. It is this Fortran subroutine that is called from the Fortran, DSDYN or DSOUT segments of your user-defined component. Constructing an interface will ensure a reasonable level of portability between the Fortran compilers available with PSCAD.
The following examples illustrate how to call a C subroutine when using the Fortran 90 compilers.
EXAMPLE 9-16:
A user has written the following simple subroutine in C, placed it into a C file (*.c).
/* User C Source Code */ void test_csub(int* arg, int* res) { *res = 6*(*arg); }
|
The user then defines an interface subroutine in a Fortran (*.f) source file as follows:
SUBROUTINE AUX_CSUB(in, out) INTEGER in, out ! ! Fortran 90 interface to a C procedure ! INTERFACE SUBROUTINE TEST_CSUB (in, out) !DEC$ ATTRIBUTES C :: TEST_CSUB !DEC$ ATTRIBUTES REFERENCE :: in !DEC$ ATTRIBUTES REFERENCE :: out ! ! in, out are passed by REFERENCE ! INTEGER in, out END SUBROUTINE END INTERFACE ! ! Call the C procedure ! CALL TEST_CSUB(in, out) END
|
A standard call statement is then added to the Fortran segment of the user component definition:
CALL AUX_CSUB($IN,$OUT)
|
Where $IN and $OUT are input and output port connections on the component respectively.