C code to replace Fortran library

Discussion in 'C Programming' started by Michael Hiegemann, Aug 29, 2003.

  1. Hello,

    I am unaware whether this is the right group to ask. Please point me
    to another forum if required.

    I would like to replace a Fortran function by one which is written in
    C. The function shall provide the same interface for the fortran code
    calling the library. Fortunately, this works - currently under WinNT -
    well for all functions which do not return a string, e.g.

    CHARACTER*16 MYSTRFUNC()

    Unfortunately, the MSDN help does not explain how to implement this
    kind of function. Also the web was not of help.

    Did I oversee something? Could anybody point me to some suitable
    information or even provide me with sample code?

    Regards, Michael
     
    Michael Hiegemann, Aug 29, 2003
    #1
    1. Advertising

  2. Michael Hiegemann

    Simon Biber Guest

    "Michael Hiegemann" <> wrote:
    > I would like to replace a Fortran function by one which is
    > written in C. The function shall provide the same interface
    > for the fortran code calling the library. Fortunately, this
    > works - currently under WinNT - well for all functions which
    > do not return a string, e.g.
    >
    > CHARACTER*16 MYSTRFUNC()


    Unfortunately, the obvious solution:
    char mystrfunc()[16];
    which is read as "declare mystrfunc as function returning array
    16 of char" is not allowed in C. You can't return an array from
    a function.

    If you are talking binary compatibility with the Fortran code then
    you will need to look into how this array return functionality is
    implemented in your Fortran compiler. That is off-topic here.

    In general C code there are at least four possible workarounds,
    presented in order from best to worst practise in C code:

    #include <stdlib.h>
    #include <string.h>

    /* Caller supplies array to fill in */
    void mystrfunc1(char *dest)
    {
    strcpy(dest, "output");
    }

    /* Caller must free the allocated memory */
    char *mystrfunc2(void)
    {
    char *p = malloc(16);
    if(p) strcpy(p, "output");
    return p;
    }

    /* Caller receives a pointer to a string literal which
    is static and unmodifyable */
    const char *mystrfunc3(void)
    {
    return "output";
    }

    /* Caller receives a pointer to a static array, which is
    overwritten if the function is called again. This is
    not safe for recursion, reentrancy or multithreading */
    char *mystrfunc4(void)
    {
    static char result[16];
    strcpy(result, "output");
    return result;
    }

    What you MUST NOT do is return a pointer to an automatic object:
    char *mystrfunc5(void)
    {
    char result[16];
    strcpy(result, "output");
    return result;
    }
    Because the result array is deallocated when the function returns
    you return an invalid pointer, and the memory may be reused before
    the caller grabs the results.

    --
    Simon.
     
    Simon Biber, Aug 29, 2003
    #2
    1. Advertising

  3. Michael Hiegemann

    LibraryUser Guest

    Simon Biber wrote:
    > "Michael Hiegemann" <> wrote:
    >
    > > I would like to replace a Fortran function by one which is
    > > written in C. The function shall provide the same interface
    > > for the fortran code calling the library. Fortunately, this
    > > works - currently under WinNT - well for all functions which
    > > do not return a string, e.g.
    > >
    > > CHARACTER*16 MYSTRFUNC()

    >

    .... snip ...
    >
    > If you are talking binary compatibility with the Fortran code then
    > you will need to look into how this array return functionality is
    > implemented in your Fortran compiler. That is off-topic here.
    >
    > In general C code there are at least four possible workarounds,
    > presented in order from best to worst practise in C code:


    You omitted defining a structure with the sole content being an
    array of char. This can be passed and returned by value.

    struct fortranstring16 {
    char data[16];
    }

    --
    Replies should be to the newsgroup
    Replace this line to publish your e-mail address.
     
    LibraryUser, Aug 29, 2003
    #3
  4. Michael Hiegemann

    Simon Biber Guest

    "LibraryUser" <> wrote:
    > You omitted defining a structure with the sole content
    > being an array of char. This can be passed and returned
    > by value.
    >
    > struct fortranstring16 {
    > char data[16];
    > }


    Yes, that is probably closer semantically to the Fortran
    code. I didn't think of it because it's not something I
    would ever do in C code.

    Returning structures by value can be implemented in many
    different ways, and may not be binary compatible with the
    Fortran compiler on the OP's system.

    --
    Simon.
     
    Simon Biber, Aug 30, 2003
    #4
  5. "Simon Biber" <> wrote in message news:<3f4f3842$0$4187$>...
    > "Michael Hiegemann" <> wrote:
    > > I would like to replace a Fortran function by one which is
    > > written in C. The function shall provide the same interface
    > > for the fortran code calling the library. Fortunately, this
    > > works - currently under WinNT - well for all functions which
    > > do not return a string, e.g.
    > >
    > > CHARACTER*16 MYSTRFUNC()

    >
    > Unfortunately, the obvious solution:
    > char mystrfunc()[16];
    > which is read as "declare mystrfunc as function returning array
    > 16 of char" is not allowed in C. You can't return an array from
    > a function.
    >
    > If you are talking binary compatibility with the Fortran code then
    > you will need to look into how this array return functionality is
    > implemented in your Fortran compiler. That is off-topic here.
    >
    > In general C code there are at least four possible workarounds,
    > presented in order from best to worst practise in C code:
    >
    > #include <stdlib.h>
    > #include <string.h>
    >
    > /* Caller supplies array to fill in */
    > void mystrfunc1(char *dest)
    > {
    > strcpy(dest, "output");
    > }
    >
    > /* Caller must free the allocated memory */
    > char *mystrfunc2(void)
    > {
    > char *p = malloc(16);
    > if(p) strcpy(p, "output");
    > return p;
    > }
    >
    > /* Caller receives a pointer to a string literal which
    > is static and unmodifyable */
    > const char *mystrfunc3(void)
    > {
    > return "output";
    > }
    >
    > /* Caller receives a pointer to a static array, which is
    > overwritten if the function is called again. This is
    > not safe for recursion, reentrancy or multithreading */
    > char *mystrfunc4(void)
    > {
    > static char result[16];
    > strcpy(result, "output");
    > return result;
    > }
    >
    > What you MUST NOT do is return a pointer to an automatic object:
    > char *mystrfunc5(void)
    > {
    > char result[16];
    > strcpy(result, "output");
    > return result;
    > }
    > Because the result array is deallocated when the function returns
    > you return an invalid pointer, and the memory may be reused before
    > the caller grabs the results.


    Simon,

    thanks a lot for the analysis. My problem seems to be close to your
    case

    /* Caller receives a pointer to a string literal which
    is static and unmodifyable */
    const char *mystrfunc3(void)
    {
    return "output";
    }

    After a lot of experiments I found that it is generally a good idea to
    define a FortranString struct type to be used in the function's
    argument list as it saves a lot of writing and is good for overview.
    For the sake of completeness I provide my results of the weekend as it
    might be a good starting point for others:

    For the Microsoft implementation of the Fortran string I got

    struct fortran_string
    {
    char * String; /* Pointer to the first character */
    unsigned long Length; /* Number of characters allocated at
    compile time */
    };
    typedef struct fortran_string FortranString;

    This is the way they insure that the string length is always. The
    actual string length is a backward iteration looking for the first
    non-white space character, to be distinguished from the number of
    characters allocated at compile time. This can be used for any void
    function argument as well and keeps the number of arguments in the C
    implementation equal to the number of arguments visible in Fortran.

    The C implementation of a Fortran function returning string is a void
    function with the very first argument representing the return string:

    void
    MYSTRFUNC(FortranString fstring /* your arguments go here */)
    {
    static const char mystring[] = "Sixteen";
    int length;

    /* Trailing blanks required */
    memset(fstring.String, ' ', fstring.Length);

    /* Avoid array bounds violation */
    length = min(fstring.Length, strlen(mystring));

    memcpy(fstring.String, mystring, length);
    }

    Thanks a lot, also to all other contributors.

    Michael
     
    Michael Hiegemann, Sep 1, 2003
    #5
  6. "Simon Biber" <> wrote in message news:<3f4f3842$0$4187$>...
    > "Michael Hiegemann" <> wrote:
    > > I would like to replace a Fortran function by one which is
    > > written in C. The function shall provide the same interface
    > > for the fortran code calling the library. Fortunately, this
    > > works - currently under WinNT - well for all functions which
    > > do not return a string, e.g.
    > >
    > > CHARACTER*16 MYSTRFUNC()

    >
    > Unfortunately, the obvious solution:
    > char mystrfunc()[16];
    > which is read as "declare mystrfunc as function returning array
    > 16 of char" is not allowed in C. You can't return an array from
    > a function.
    >
    > If you are talking binary compatibility with the Fortran code then
    > you will need to look into how this array return functionality is
    > implemented in your Fortran compiler. That is off-topic here.
    >
    > In general C code there are at least four possible workarounds,
    > presented in order from best to worst practise in C code:
    >
    > #include <stdlib.h>
    > #include <string.h>
    >
    > /* Caller supplies array to fill in */
    > void mystrfunc1(char *dest)
    > {
    > strcpy(dest, "output");
    > }
    >
    > /* Caller must free the allocated memory */
    > char *mystrfunc2(void)
    > {
    > char *p = malloc(16);
    > if(p) strcpy(p, "output");
    > return p;
    > }
    >
    > /* Caller receives a pointer to a string literal which
    > is static and unmodifyable */
    > const char *mystrfunc3(void)
    > {
    > return "output";
    > }
    >
    > /* Caller receives a pointer to a static array, which is
    > overwritten if the function is called again. This is
    > not safe for recursion, reentrancy or multithreading */
    > char *mystrfunc4(void)
    > {
    > static char result[16];
    > strcpy(result, "output");
    > return result;
    > }
    >
    > What you MUST NOT do is return a pointer to an automatic object:
    > char *mystrfunc5(void)
    > {
    > char result[16];
    > strcpy(result, "output");
    > return result;
    > }
    > Because the result array is deallocated when the function returns
    > you return an invalid pointer, and the memory may be reused before
    > the caller grabs the results.


    Simon,

    thanks a lot for the analysis. My problem seems to be close to your
    case

    /* Caller receives a pointer to a string literal which
    is static and unmodifyable */
    const char *mystrfunc3(void)
    {
    return "output";
    }

    After a lot of experiments I found that it is generally a good idea to
    define a FortranString struct type to be used in the function's
    argument list as it saves a lot of writing and is good for overview.
    For the sake of completeness I provide my results of the weekend as it
    might be a good starting point for others:

    For the Microsoft implementation of the Fortran string I got

    struct fortran_string
    {
    char * String; /* Pointer to the first character */
    unsigned long Length; /* Number of characters allocated at
    compile time */
    };
    typedef struct fortran_string FortranString;

    This is the way they insure that the string length is always. The
    actual string length is a backward iteration looking for the first
    non-white space character, to be distinguished from the number of
    characters allocated at compile time. This can be used for any void
    function argument as well and keeps the number of arguments in the C
    implementation equal to the number of arguments visible in Fortran.

    The C implementation of a Fortran function returning string is a void
    function with the very first argument representing the return string:

    void
    MYSTRFUNC(FortranString fstring /* your arguments go here */)
    {
    static const char mystring[] = "Sixteen";
    int length;

    /* Trailing blanks required */
    memset(fstring.String, ' ', fstring.Length);

    /* Avoid array bounds violation */
    length = min(fstring.Length, strlen(mystring));

    memcpy(fstring.String, mystring, length);
    }

    Thanks a lot, also to all other contributors.

    Michael
     
    Michael Hiegemann, Sep 1, 2003
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Christopher M. Lusardi

    How To Get To Fortran Common Variables Within a C Code

    Christopher M. Lusardi, Jan 16, 2004, in forum: C Programming
    Replies:
    5
    Views:
    1,028
    glen herrmannsfeldt
    Jan 31, 2004
  2. Shawn
    Replies:
    14
    Views:
    907
  3. sam

    convert 'C' code to 'Fortran'

    sam, Nov 10, 2004, in forum: C Programming
    Replies:
    26
    Views:
    4,081
    Michael Wojcik
    Nov 24, 2004
  4. Luna Moon
    Replies:
    9
    Views:
    645
    Guest
    Sep 4, 2007
  5. deadpickle
    Replies:
    1
    Views:
    1,095
    Jens Thoms Toerring
    Nov 7, 2010
Loading...

Share This Page