Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Cross compiling problem of getarg

FortCpp
Beginner
829 Views
0 Kudos
14 Replies
Steven_L_Intel1
Employee
829 Views

Why are you calling the Fortran internal  run-time library routines from C?  That's not supported.

I think your prototype of for_getarg is wrong. I'd expect there to be four arguments to it (the character argument takes an address and length, and you need to supply a NULL for the status argument if not using it. Why you use "short" I also don't understand.

If you want the Fortran functionality, write a Fortran routine that calls getarg and call that - or use GET_COMMAND_ARGUMENT.

0 Kudos
TimP
Honored Contributor III
829 Views

Could you drop the legacy hacks and use get_command_argument ?

0 Kudos
FortCpp
Beginner
829 Views

removed

0 Kudos
FortCpp
Beginner
829 Views

TimP (Intel) wrote:

Could you drop the legacy hacks and use get_command_argument ?

Hi TimP. I am compiling a library and there is a same error. That's not my idea.

Trust me. I'd use getarg/get_command_argument, not the functions in my post for my own code. 

Sorry for the confuse.

0 Kudos
Steven_L_Intel1
Employee
829 Views

That's the correct page for the GETARG intrinsic. But the internal routine it calls will actually have four arguments - the argument number, address of character string, address of status argument (or 0 if omitted), and a "size_t" integer for the length of the character argument, passed by value. You are passing the wrong datatypes and passing the length by reference rather than value. You're lucky you got an access violation given how wrong this code is.

Rather than trying to patch it over, please do it right.

0 Kudos
FortCpp
Beginner
829 Views

Steve Lionel (Intel) wrote:

That's the correct page for the GETARG intrinsic. But the internal routine it calls will actually have four arguments - the argument number, address of character string, address of status argument (or 0 if omitted), and a "size_t" integer for the length of the character argument, passed by value. You are passing the wrong datatypes and passing the length by reference rather than value. You're lucky you got an access violation given how wrong this code is.

Rather than trying to patch it over, please do it right.

Thanks Steve. Now I get it.

0 Kudos
TimP
Honored Contributor III
829 Views

In line with what Steve said, internal implementations of the legacy getarg function will differ among various Fortran implementations; besides, a web search shows open source implementations with little documentation which may have been copied from libf2c (an early implementation of F77 runtime).  Although that was last used with g77, normal usage would not have involved calling the internal C implementation directly, even when using Fortran compilation based on f2c.  So, using poorly conceived open source which depends on a particular seldom used interface has limitations.  libf2c functions will conflict with the run-time libraries of current Fortran compilers.

0 Kudos
FortCpp
Beginner
829 Views

TimP (Intel) wrote:

In line with what Steve said, internal implementations of the legacy getarg function will differ among various Fortran implementations; besides, a web search shows open source implementations with little documentation which may have been copied from libf2c (an early implementation of F77 runtime).  Although that was last used with g77, normal usage would not have involved calling the internal C implementation directly, even when using Fortran compilation based on f2c.  So, using poorly conceived open source which depends on a particular seldom used interface has limitations.  libf2c functions will conflict with the run-time libraries of current Fortran compilers.

Thanks TimP. I don't know much about libf2c. I am not sure whether the code that I am compiling has any relationship to libf2c. But thanks for telling me the knowledge. Here is the link for the code (maybe you want to take a look): https://bitbucket.org/petsc/petsc-3.3/src/70ed804d1752b201e3262bb8d1826a110fee28fe/src/sys/ftn-custom/zstart.c

You are right. I am compiling it for personal use currently. I am not a pro like you, so I just want to have it compiled...

The error goes away when I use for_getcmd_arg with four prameters (that I followed Steve's suggestion) instead of for_getarg with three prameters. But I still don't understand how things work. So far it seems that GET_COMMAND_ARGUMENT works like a macro. And will be replaced by for_getarg when there are 3 prameters, by for_getcmd_arg when 4. I don't see why for_getcmd_arg gives no error message but for_getarg does. If you use GET_COMMAND_ARGUMENT in the c code (getarg.c), it will fail when linking. 

0 Kudos
Steven_L_Intel1
Employee
829 Views
GET_COMMAND_ARGUMENT is not a macro, it's a standard intrinsic subroutine. It just happens to do the same thing as GETARG (at least the way we have implemented it), so we may have chosen to use the same library routine for it. I didn't mean that you should use GET_COMMAND_ARGUMENT in the C code, but rather in the Fortran code. On Windows, you could just call the C getarg and iargc and stop messing with the Fortran internal library.
0 Kudos
FortCpp
Beginner
829 Views

Sorry for messing the Fortran internal library. It seems my post makes intel developer feel bad. And I did something improper. I shall remove all of my posts. I wanted to know how, not to hurt you.

0 Kudos
Steven_L_Intel1
Employee
829 Views
You haven't hurt anyone but yourself. I am certainly not offended in any way - just trying to set you on the right path.
0 Kudos
FortCpp
Beginner
829 Views

Hi Steve and Timp,

I read a lot last week. Now I understand you better. Sorry for the misunderstood 2 weeks ago. I didn't have enough knowledge that day when I discuss this problem. So this time, would you please take a look at my code? Hope I did it OK this time. I appreciate your patient and time.

Fortran side:

[fortran]

subroutine getstring(number, name, nlen, status) bind(C,name='mygetarg')
use, intrinsic :: iso_c_binding
implicit none
integer(kind=c_int), intent(IN) :: number
character(kind=c_char), dimension(256), intent(INOUT) :: name
integer(kind=c_int), intent(INOUT) :: nlen
integer(kind=c_int), intent(INOUT) :: status
character(len=256) :: name_tmp

call get_command_argument(number, name_tmp, nlen, status)
name=transfer(name_tmp, name)
end subroutine getstring

[/fortran]

c side:

[cpp]

extern void mygetarg(int*,char*,int*,int*);

int nlen, status;
int ishift = i+1;

char name[256];
mygetarg(&ishift,name,&nlen, &status);

[/cpp]

fortran code compiled with /iface:cref.

Here I am not sure about the "Character-length argument passing". Does it mean I have to write subroutine with four arguments in fortran, and extern void mygetarg with 5 arguments in c to make it right? What will happen if they don't match?

0 Kudos
Steven_L_Intel1
Employee
829 Views

This code is almost right., First, you don't need /iface here. Second, when you use BIND(C), there are no hidden arguments, so you have declared it right. The only thing I see as a problem is that get_command_argument will not put a NUL at the end of the string, which the C code will want. Since you're getting the length back in nlen, you can use that.

0 Kudos
FortCpp
Beginner
829 Views

Thanks Steve! I'll add a 0 in the end of the string.

0 Kudos
Reply