C code to replace Fortran library

M

Michael Hiegemann

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
 
S

Simon Biber

Michael Hiegemann said:
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.
 
L

LibraryUser

Simon said:
.... 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];
}
 
S

Simon Biber

LibraryUser said:
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.
 
M

Michael Hiegemann

Simon Biber said:
Michael Hiegemann said:
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
 
M

Michael Hiegemann

Simon Biber said:
Michael Hiegemann said:
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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,534
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top