链接已复制
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.
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.
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.
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.
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.
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.
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?
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.
