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.