CCP4 Coordinate Library Project

RWBROOK interface functions: Using the Interface from Programs Written in C and C++.


GENERAL REMARKS

First of all, there is no special need to use RWBROOK from C and C++. Programs written in these languages, may use a more powerful Object Interface. This interface gives access to many Library functions that are not accessible through RWBROOK. At present, there are no plans of extending RWBROOK functionality.

 

TECHNICAL NOTES

All RWBROOK functions, although written in C++, are implemented as FORTRAN subroutines. Your C or C++ code must be able to link to FORTRAN code, and this is all what needed.

The definitions of RWBROOK functions are collected in header file mmdb_rwbrook.h. In order to invoke the definitions into C/C++ code, this file should be simply included on the top of the corresponding program files:

#include "mmdb_rwbrook.h"

Programs written and compiled in plain C, also must set on the definition of __PlainC before including the mmdb_rwbrook.h:

#define __PlainC
#include "mmdb_rwbrook.h"

NOTE: a program written in plain C may be compiled with a C++ compiler as well. If this is the case, the definition of __PlainC must not be set on.

Linking C/C++ and FORTRAN is architecture-dependent. The Library provides a few useful macros, which unify C/C++ <=> FORTRAN linking over variety of platforms (the list of acceptible platforms is found in file machine_.h). Definitions of these macros come automatically with the inclusion of mmdb_rwbrook.h. The macros are described below.

INDEX OF C/C++ <=> FORTRAN LINKING MACROS
FORTRAN_CALL
FORTRAN_SUBR
char_struct
fill_char_struct
FTN_STR
FTN_LEN

 


FORTRAN_CALL ( name_in_capital,name_in_small,
               ( length_at_end_list ),
               ( length_in_structure_list ),
               ( length_follow_list ) )
PURPOSE:
Makes a platform-independent link to a FORTRAN subroutine.

PARAMETERS:

name_in_capital
name of FORTRAN subroutine in capital letters.

name_in_small
name of FORTRAN subroutine in small letters.

length_at_end_list
list of parameters, which are to be passed to the FORTRAN subroutine, with lengths of string parameters collected at the end. Non-string parameters are passed as pointers.

String parameters must be declared as having the char_struct macro-type, or they must come as fpstr parameters of macro FORTRAN_SUBR. The char_struct macro-type has different implementation for different platforms.

The lengths of string parameters are passed as values in the end of length_at_end_list, preserving the order of string parameters. The names of string lengths must be composed as StrName_len, where StrName is name of the corresponding string parameter. Parameters are separated by commas. See examples below.

length_in_structure_list
list of parameters, which are to be passed to the FORTRAN subroutine, with strings and their lengths combined into a special structure. Non-string parameters are passed as pointers.

String parameters must be declared as having the char_struct macro-type, or they must come as fpstr parameters of macro FORTRAN_SUBR.

The lengths of string parameters are not specified explicitely in this list. The parameter list replicates precisely that one of the actual FORTRAN subroutine. Parameters are separated by commas. See examples below.

length_follow_list
list of parameters, which are to be passed to the FORTRAN subroutine, with strings are immedistely followed by their lengths. Non-string parameters are passed as pointers.

String parameters must be declared as having the char_struct macro-type, or they must come as fpstr parameters of macro FORTRAN_SUBR.

The length of each string parameter is passed as a value and it must immediately follow the string parameter. The names of string lengths must be composed as StrName_len, where StrName is name of the corresponding string parameter. Parameters are separated by commas. See examples below.

 

EXAMPLE 1

FORTRAN subroutine

subroutine XYZClose ( iUnit,iRet )
integer    iUnit,iRet

should be linked (called) from a C/C++ module as

int  iUnit,iRet;
...............
FORTRAN_CALL ( XYZCLOSE,xyzclose,
               ( *iUnit,*iRet ),  // length-at-end list
               ( *iUnit,*iRet ),  // length-in-structure list
               ( *iUnit,*iRet )   // length-follow list
             );

In this example, there is no string parameters to pass into FORTRAN subroutine, therefore all three parameter lists are identical.

 

EXAMPLE 2

FORTRAN subroutine

subroutine XYZOpen ( LName,RWStat,FType,iUnit,iRet )
character*(*) LName,RWStat,FType
integer       iUnit,iRet

should be linked (called) from a C/C++ module as

int    iUnit,iRet;
char_struct(LName)
char_struct(RWStat)
char_struct(FType)

...............

fill_char_struct ( FName ,"XYZIN" )
fill_char_struct ( RWStat,"INPUT" )
fill_char_struct ( FTYPE ,"CIF"   )

FORTRAN_CALL ( XYZOPEN,xyzopen,
               (    // lengths-at-end list
                LName,RWStat,FType,*iUnit,*iRet,
                LName_len,RWStat_len,FType_len
               ), ( // lengths-in-structure list
                LName,RWStat,FType,*iUnit,*iRet       
               ), ( // lengths-follow list
                LName,LName_len, RWStat,RWStat_len,   
                FType,FType_len, *iUnit,*iRet
               )
             );

Note that there is no explicit declarations for string length parameters LName_len, RWStat_len and FType_len; do not declare string lengths if macro char_struct is used. Note also the way of handling the macro-type char_struct variables.

 

REMARKS: It is important to keep the suggested way of C/C++ <=> FORTRAN linking if you want your programs to be portable between different platforms. Note the special way of handling the macro-type char_struct variables. Generally, you should not handle these variables directly but through macros char_struct, FTN_STR and char_struct only.

An attention should be given to the real-type parameters, which are to be passed to a FORTRAN subroutine. As a standard, RWBROOK uses real*4 real types in its FORTRAN interface. This is defined by type apireal found on the top of file mmdb_rwbrook.h. This type may be freely changed to real*8, if necessary (the corresponding line in mmdb_rwbrook.h is commented, cf. there). This definition does not affect non-RWBROOK FORTRAN subroutines, therefore they should be given special attention.

 


FORTRAN_SUBR ( name_in_capital,name_in_small,
               ( length_at_end_list ),
               ( length_in_structure_list ),
               ( length_follow_list ) )
PURPOSE:
Makes a platform-independent definition of a FORTRAN subroutine.

PARAMETERS:

name_in_capital
name of FORTRAN subroutine in capital letters.

name_in_small
name of FORTRAN subroutine in small letters.

length_at_end_list
list of parameters, which are to be passed to the FORTRAN subroutine, with lengths of string parameters collected at the end. Non-string parameters are declared as pointers. Real-type parameters in RWBROOK are declared as 'apireal *'.

String parameters must be declared as having the fpstr type. This type has different implementation on different platforms.

The lengths of string parameters are declared as values in the end of length_at_end_list, preserving the order of string parameters. The names of string lengths must be composed as StrName_len, where StrName is name of the corresponding string parameter. Parameters are separated by commas. See examples below.

length_in_structure_list
list of parameters, which are to be passed to the FORTRAN subroutine, with strings and their lengths combined into a special structure. Non-string parameters are passed as pointers. Real-type parameters in RWBROOK are declared as 'apireal *'.

String parameters must be declared as having the fpstr type.

The lengths of string parameters are not specified explicitely in this list. The parameter list replicates precisely that one of the actual FORTRAN subroutine. Parameters are separated by commas. See examples below.

length_follow_list
list of parameters, which are to be passed to the FORTRAN subroutine, with strings are immedistely followed by their lengths. Non-string parameters are passed as pointers. Real-type parameters in RWBROOK are declared as 'apireal *'.

String parameters must be declared as having the fpstr type.

The length of each string parameter is declared as a value and it must immediately follow the string parameter. The names of string lengths must be composed as StrName_len, where StrName is name of the corresponding string parameter. Parameters are separated by commas. See examples below.

 

EXAMPLE 1

FORTRAN subroutine

subroutine XYZClose ( iUnit,iRet )
integer    iUnit,iRet

gets the following declaration in a C/C++ module:

FORTRAN_SUBR ( XYZCLOSE,xyzclose,
               ( int * iUnit, int * iRet ),  // length-at-end list
               ( int * iUnit, int * iRet ),  // length-in-structure list
               ( int * iUnit, int * iRet )   // length-follow list
             );

In this example, there is no string parameters to pass into FORTRAN subroutine, therefore all three parameter lists are identical.

 

EXAMPLE 2

FORTRAN subroutine

subroutine XYZOpen ( LName,RWStat,FType,iUnit,iRet )
character*(*) LName,RWStat,FType
integer       iUnit,iRet

is declared in a C/C++ module as

FORTRAN_SUBR ( XYZOPEN,xyzopen,
               (    // lengths-at-end list
                fpstr LName,  fpstr RWStat, fpstr FType,
                int * iUnit,  int * iRet,
                int   LName_len,
                int   RWStat_len,
                int   FType_len
               ), ( // lengths-in-structure list
                fpstr LName,  fpstr RWStat, fpstr FType,      
                int * iUnit,  int * iRet       
               ), ( // lengths-follow list
                fpstr LName,  int LName_len,    
                fpstr RWStat, int RWStat_len,   
                fpstr FType,  int FType_len,   
                int * iUnit,  int * iRet
               )
             );

 

EXAMPLE 3

FORTRAN subroutine

subroutine XYZCoord1 ( iUnit,XFlag,BFlag,
                       x,y,z,occ,BIso,U,iRet )
integer       iUnit,iRet
character*(*) XFlag,BFlag
real          x,y,z,occ,BIso,U(6)

is declared in a C/C++ module as

FORTRAN_SUBR ( XYZCOORD1,xyzcoord1,
               (    // lengths-at-end list
                int * iUnit,    // unit number
                fpstr XFlag,    // "F" or "O" flag for the fractional
                                // or orthogonal coordinates x,y,z
                                // for output files XFlag may also be
                                // set to "HF" or "HO", where "F" and
                                // "O" have the same meaning as before
                                // and "H" indicates that the atom
                                // should be marked as heteroatom
                fpstr BFlag,    // "F" or "O" flag for temperature
                                // factor in fractional or orthogonal
                                // Us
                apireal * x,    // x-coordinate
                apireal * y,    // y-coordinate
                apireal * z,    // z-coordinate
                apireal * occ,  // occupancy
                apireal * BIso, // isotropic temperature factor
                apireal * U,    // array(6) of the anisotr. t-factor
                int * iRet,     // returns
                                //  RWBERR_NoChannel     if iUnit was not
                                //                       initialized
                                //  RWBERR_EmptyPointer  if atom was not
                                //                       advanced
                                //  RWBERR_NoMatrices    if transformation
                                //                       matrices are
                                //                       undefined
                                //  RWBERR_NoCoordinates if coordinates were
                                //                       not set in the atom
                                //
                                //  >=0 : success, warning flags:
                                //  RWBERR_NoOccupancy   if occupancy was  
                                //                       not set in the atom
                                //  RWBERR_NoTempFactor  if temp. factor was
                                //                       not set in the atom
                                //
                int XFlag_len,  // fortran-hidden length of XFlag
                int BFlag_len   // fortran-hidden length of BFlag
               ), ( // lengths-in-structure list
                int * iUnit,   fpstr XFlag,    fpstr BFlag,
                apireal * x,   apireal * y,    apireal * z,
                apireal * occ, apireal * BIso, apireal * U,
                int * iRet
               ), ( // lengths-follow list
                int * iUnit,
                fpstr XFlag,   int XFlag_len,
                fpstr BFlag,   int BFlag_len,
                apireal * x,   apireal * y,    apireal * z,
                apireal * occ, apireal * BIso, apireal * U,
                int * iRet
               )
             );

In this example, put attention on the way of declaration of real-type parameters.

 

REMARKS:

It is important to keep the suggested way of C/C++ <=> FORTRAN linking if you want your programs to be portable between different platforms.

An attention should be given to the real-type parameters, which are to be passed to a FORTRAN subroutine. As a standard, RWBROOK uses real*4 real types in its FORTRAN interface. This is defined by type apireal found on the top of file mmdb_rwbrook.h. This type may be freely changed to real*8, if necessary (the corresponding line in mmdb_rwbrook.h is commented, cf. there). This definition does not affect non-RWBROOK FORTRAN subroutines, therefore they should be given special attention.

 


char_struct(StrName)
PURPOSE:
Makes a platform-independent definition of a string parameter, which can be passed to a FORTRAN subroutine.

PARAMETERS:

StrName
name of the string parameter

 

REMARKS:

Implementation of char_struct is platform-dependent, but in any case it declares a pointer to the string buffer and an integer containing its length. It is advisable to use this definition only for parameters which are to be passed to a FORTRAN subroutine. There are three important points to note here.

First, a char_struct-variable does not allocate space for the string's buffer. A char_struct-variable should be neither allocated nor disposed dynamically.

Second, one should never try to access a char_struct-variable directly. These variables are assigned values with macro fill_char_struct before passing into a FORTRAN subroutine. An example of this technique is given above. One should never try to retrieve data from a char_struct-variable, except for the FORTRAN subroutine, into which the variable is passed.

Third, in declarations of FORTRAN subroutines inside C/C++ modules, char_struct-variables are referred to as having the fpstr type. The string is retrieved from fpstr variable with macro FTN_STR, and length of the string's buffer - with macro FTN_LEN. Both macros FTN_STR and FTN_LEN may appear on the left side of assignment operator, however one is not allowed to change the length of buffer of the string passed into a FORTRAN subroutine.

 


fill_char_struct(StrName,Str)
PURPOSE:
Assignes a value to a char_struct variable.

PARAMETERS:

StrName
name of a char_struct variable

Str
string that is to be assigned to char_struct variable StrName.

 

REMARKS:

Since implementation of char_struct variables is platform-dependent, one should never try to assign any values to such variables directly. Using the macro fill_char_struct is the only correct way of doing that. An example of this technique is given above. See also remarks made for using the char_struct macro.

 


FTN_STR(StrName)
PURPOSE:
Returns pointer to the string passed as a fpstr parameter into a FORTRAN-interface function (declared with macro FORTRAN_SUBR) in a C/C++ module.

PARAMETERS:

StrName
name of a fpstr variable.

 

REMARKS:

Since implementation of fpstr variables is platform-dependent, one should never try either to assign any values to such variables nor to retrieve them directly. Using the macro FTN_STR is the only correct way of doing that. The macro must not appear on the left side of assignment operator. The following example demonstrates usage of macros FTN_STR and FTN_LEN:

A C/C++ equivalent of FORTRAN subroutine

      subroutine JustSomething ( A )
      character*(*) A
      write ( *,1000 )  len(A),A
      A = '0123456789'
      return
 1000 format ( I5,A )
      end

looks like the following:

FORTRAN_SUBR ( JUSTSOMETHING,justsomething,
               ( fpstr A, int A_len ),
               ( fpstr A ),
               ( fpstr A, int A_len ) )  {
  printf  ( "%5i     %s\n",FTN_LEN(A),FTN_STR(A) );
  memset  ( FTN_STR(A),' ',FTN_LEN(A) );
  strncpy ( FTN_STR(A),"0123456789",strlen("0123456789") );
}

where we assume that length of buffer for string A is gretaer than 10. Note that there is no explicit use of A_len parameter.

 


FTN_LEN(StrName)
PURPOSE:
Returns length of the buffer of the string passed as a fpstr parameter into a FORTRAN-interface function (declared with macro FORTRAN_SUBR) in a C/C++ module.

PARAMETERS:

StrName
name of a fpstr variable.

 

REMARKS:

The macro may be used only for learning the physical length of fpstr-string's buffer. Since implementation of fpstr variables is platform-dependent, one should never try to find this length by direct reading the fpstr fields. Using the macro FTN_LEN is the only correct way of doing that. The macro must not appear on the left side of assignment operator. Usage of macros FTN_LEN and FTN_STR is demonstrated above.

 


Back to index