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.
 
 
PARAMETERS:
 
 
 
    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.
     
 
    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.
     
 
    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
 
 
should be linked (called) from a C/C++ module as
 
 
In this example, there is no string parameters to pass into
FORTRAN subroutine, therefore all three parameter lists
are identical.
  
 
EXAMPLE 2
 
FORTRAN subroutine
 
 
should be linked (called) from a C/C++ module as
 
 
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.
  
 
 
 
PARAMETERS:
 
 
 
    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.
      
 
EXAMPLE 1
 
FORTRAN subroutine
 
 
gets the following declaration in a C/C++ module:
 
 
In this example, there is no string parameters to pass into
FORTRAN subroutine, therefore all three parameter lists
are identical.
  
 
EXAMPLE 2
 
FORTRAN subroutine
 
 
is declared in a C/C++ module as
 
  
 
EXAMPLE 3
 
FORTRAN subroutine
 
 
is declared in a C/C++ module as
 
 
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.
  
 
 
 
PARAMETERS:
 
  
 
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.
  
 
 
 
PARAMETERS:
 
 
  
 
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.
  
 
 
 
PARAMETERS:
 
  
 
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
 
looks like the following:
 
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.
  
 
 
 
PARAMETERS:
 
  
 
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.
  
 
FORTRAN_CALL ( name_in_capital,name_in_small,
               ( length_at_end_list ),
               ( length_in_structure_list ),
               ( length_follow_list ) )
subroutine XYZClose ( iUnit,iRet )
integer    iUnit,iRet
int  iUnit,iRet;
...............
FORTRAN_CALL ( XYZCLOSE,xyzclose,
               ( *iUnit,*iRet ),  // length-at-end list
               ( *iUnit,*iRet ),  // length-in-structure list
               ( *iUnit,*iRet )   // length-follow list
             );
subroutine XYZOpen ( LName,RWStat,FType,iUnit,iRet )
character*(*) LName,RWStat,FType
integer       iUnit,iRet
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
               )
             );
FORTRAN_SUBR ( name_in_capital,name_in_small,
               ( length_at_end_list ),
               ( length_in_structure_list ),
               ( length_follow_list ) )
subroutine XYZClose ( iUnit,iRet )
integer    iUnit,iRet
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
             );
subroutine XYZOpen ( LName,RWStat,FType,iUnit,iRet )
character*(*) LName,RWStat,FType
integer       iUnit,iRet
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
               )
             );
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)
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
               )
             );
char_struct(StrName)
fill_char_struct(StrName,Str)
FTN_STR(StrName)
variable.
      subroutine JustSomething ( A )
      character*(*) A
      write ( *,1000 )  len(A),A
      A = '0123456789'
      return
 1000 format ( I5,A )
      end
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") );
}
FTN_LEN(StrName)
variable.