Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

recursive callback between Fortran and C

50 views
Skip to first unread message

brtnfld

unread,
Oct 4, 2011, 2:08:04 AM10/4/11
to
I'm trying to do a recursive callback of a fortran function from a C
function.

The "recursive" fortran function I callback looks something like:

INTEGER FUNCTION op_func2() BIND(C)

TYPE(C_FUNPTR) :: funptr2

funptr2 = C_FUNLOC(op_func2)

CALL C_routine_that_calls_op_func2_again(funptr2)

END

the C call looks something like:

ret_value = (udata->op)();

Every time the C function calls the fortran callback routine it seg
faults on the C call to the fortran function.

If I instead create an identical function of op_func2 (say op_func3)
and change in op_func2:

funptr2 = C_FUNLOC(op_func3)

Then that works, but I would like to use the op_func2 as a recursive
function and not create a limitless number of functions for op_func.

Am I missing something or is this not possible to do.

glen herrmannsfeldt

unread,
Oct 4, 2011, 2:37:36 AM10/4/11
to
brtnfld <epil...@att.net> wrote:
> I'm trying to do a recursive callback of a fortran function from a C
> function.

> The "recursive" fortran function I callback looks something like:

> INTEGER FUNCTION op_func2() BIND(C)

First, your function should have the RECURSIVE option.

> TYPE(C_FUNPTR) :: funptr2

> funptr2 = C_FUNLOC(op_func2)

Interesting that the compiler didn't catch this one. Note that inside
a function without the RESULT option the function name is a variable,
and so, I would expect, you have the address of the variable, not the
function.

Use the RESULT option, return the value through that variable, and
op_func2 will be the function address.

-- glen

Louisa

unread,
Oct 4, 2011, 6:37:45 AM10/4/11
to
On Oct 4, 5:08 pm, brtnfld <epilo...@att.net> wrote:
> I'm trying to do a recursive callback of a fortran function from a C
> function.
>
> The "recursive" fortran function I callback looks something like:

To call a FORTRAN procedure recursively, you must use "RECURSIVE".

RECURSIVE INTEGER FUNCTION op_func2() BIND(C)

Louisa

unread,
Oct 4, 2011, 6:40:36 AM10/4/11
to
On Oct 4, 5:37 pm, glen herrmannsfeldt <g...@ugcs.caltech.edu> wrote:
> brtnfld <epilo...@att.net> wrote:
> > I'm trying to do a recursive callback of a fortran function from a C
> > function.
> > The "recursive" fortran function I callback looks something like:
> > INTEGER FUNCTION op_func2() BIND(C)
>
> First, your function should have the RECURSIVE option.
>
> > TYPE(C_FUNPTR) :: funptr2
> > funptr2 = C_FUNLOC(op_func2)
>
> Interesting that the compiler didn't catch this one.

It can't. The Fortran compiler can't tell that it's being called
recursively, because it's the C code that's calling.

glen herrmannsfeldt

unread,
Oct 4, 2011, 9:29:52 AM10/4/11
to
Louisa <louisa...@gmail.com> wrote:

>> > funptr2 = C_FUNLOC(op_func2)

(then I wrote)
>> Interesting that the compiler didn't catch this one.

> It can't. The Fortran compiler can't tell that it's being called
> recursively, because it's the C code that's calling.

op_func2 is a variable name, not a procedure name as the argument
of C_FUNLOC is supposed to have. Try calling op_func2 from inside,
the compiler should catch that one. Try calling C_FUNLOC() with
any other variable name.

-- glen

brtnfld

unread,
Oct 6, 2011, 1:52:53 AM10/6/11
to
I tried:

RECURSIVE INTEGER FUNCTION op_func() RESULT(ret_val) BIND(C)
TYPE(C_FUNPTR) :: funptr

funptr = C_FUNLOC(op_func)


and I verified the address of funptr is correctly passed to the C code.
Stepping through the assembly code it segfaults at

0x00007fff08084ac0 20 dd and ch, bl

where 0x00007fff08084ac0 is the address given by funptr, 20 dd is the
Opcode and "and ch, bl" is the Source. I don't know what that means.

If I do:

funptr = C_FUNLOC(op_func)

in another subroutine (i.e. not within the recursive function), then on
the C side the debugger shows the address and the function name:

0x404d34 <op_func>

but for the recursive function, the debugger shows in C just the address,
no function name, which seems odd, but maybe it's nothing.

glen herrmannsfeldt

unread,
Oct 6, 2011, 2:10:20 AM10/6/11
to
brtnfld <epil...@att.net> wrote:

> RECURSIVE INTEGER FUNCTION op_func() RESULT(ret_val) BIND(C)
> TYPE(C_FUNPTR) :: funptr

> funptr = C_FUNLOC(op_func)

> and I verified the address of funptr is correctly passed to the C code.
> Stepping through the assembly code it segfaults at

If the address is correctly passed, it should work.

Just to be sure, you either declare the argument of the C routine
as VALUE, or you get a pointer to the function pointer, which you
have to dereference. But that should be the same for the non-recursive
case, which you say works.

> 0x00007fff08084ac0 20 dd and ch, bl

> where 0x00007fff08084ac0 is the address given by funptr, 20 dd is the
> Opcode and "and ch, bl" is the Source. I don't know what that means.

> If I do:

> funptr = C_FUNLOC(op_func)

> in another subroutine (i.e. not within the recursive function), then on
> the C side the debugger shows the address and the function name:

> 0x404d34 <op_func>

> but for the recursive function, the debugger shows in C just the address,
> no function name, which seems odd, but maybe it's nothing.

-- glen

brtnfld

unread,
Oct 6, 2011, 3:03:35 AM10/6/11
to

>
> If the address is correctly passed, it should work.
>
> Just to be sure, you either declare the argument of the C routine as
> VALUE, or you get a pointer to the function pointer, which you have to
> dereference. But that should be the same for the non-recursive case,
> which you say works.

The first case, for the interface to the C routine I have:

TYPE(C_FUNPTR), VALUE :: op

HOWEVER, I switched from Intel's compiler to gfortran/gcc 4.5.1 and it
WORKS BEAUTIFULLY!!! I reeallly wish I would have done that earlier, I
guess the Intel compiler has a bug.

Thanks for the help all.

Robert Miles

unread,
Oct 8, 2011, 1:10:41 AM10/8/11
to

The C compiler I'm familiar with (Cygwin gcc, under Windows) requires
you to tell it which modules you want to be recursive so it can assign
each call to the module a separate dataspace for values it can change.
You may need to check if your Fortran compiler has the same requirement,
and whether it can handle recursive calls at all.

0 new messages