Re: [f2py] Unexpected text pyfunction_cptr encountered

Pearu Peterson <[email protected]> Sat, 16 Oct 2010 21:48:59 +0300
Newsgroups gmane.comp.python.f2py.user
Message-ID <[email protected]>
Hi,
The ending 'E' problem is now fixed in numpy git repo.
Pearu

On Sat, Oct 16, 2010 at 8:44 PM,  <[email protected]> wrote:
> Hi Pearu,
>
> Thank you so much for your help!
>
> Don't worry about the 'E'!  The 'E' is probably due to array bounds write; ASTRING is allocated 10 chars, you overflowed it.  ;)
>
> Mark
> ----- Original Message -----
> From: Pearu Peterson <[email protected]>
> Date: Saturday, October 16, 2010 5:49 am
> Subject: Re: [f2py] Unexpected text pyfunction_cptr encountered
> To: For users of the f2py program <f2py-users-Y4l6ocDipWCuvFJfX82//[email protected]>
>
>
>> Hi,
>> You can use the f2py intent(callback) feature to achieve what you have
>> described. Here follows an example:
>>
>> c foo.f
>>       SUBROUTINE A()
>> c     the following 2 lines say that f2py should construct the
>> run_python function
>> cf2py intent(callback) RUN_PYTHON
>>       EXTERNAL RUN_PYTHON
>>       CHARACTER*10 ASTRING
>> c     the following line defines the signature for run_python function
>> cf2py call run_python(astring)
>>       PRINT*, "ENTERING A"
>>       ASTRING = "abcdefghijklm"
>>       CALL B(ASTRING)
>>       PRINT*, "LEAVING A"
>>       RETURN
>>       END
>>
>>       SUBROUTINE B(ASTRING)
>> c
>> c       Cannot change this routine
>> c
>>       CHARACTER*10 ASTRING
>>       PRINT*, "ENTERING B"
>>       CALL C(ASTRING)
>>       PRINT*, "LEAVING B"
>>       RETURN
>>       END
>>
>>       SUBROUTINE C(ASTRING)
>>       EXTERNAL RUN_PYTHON
>>       CHARACTER*10 ASTRING
>>       PRINT*, "ENTERING C"
>>       CALL RUN_PYTHON(ASTRING)
>>       PRINT*, "LEAVING C"
>>       RETURN
>>       END
>> c end of foo.f
>>
>> Build the extension module:
>>
>> f2py -c -m foo foo.f
>>
>> Usage from Python:
>>
>> >>> import foo
>> >>> def func(string): print "entering func(%r)" % (string)
>> ...
>> >>> foo.a(func)
>>  ENTERING A
>>  ENTERING B
>>  ENTERING C
>> entering func('abcdefghijE')
>>  LEAVING C
>>  LEAVING B
>>  LEAVING A
>> >>> # note that function `a` takes callable argument while fortran
>> subroutine `a` defined is as external function
>> >>> print(foo.a.__doc__)
>> a - Function signature:
>>   a(run_python,[run_python_extra_args])
>> Required arguments:
>>   run_python : call-back function
>> Optional arguments:
>>   run_python_extra_args := () input tuple
>> Call-back functions:
>>   def run_python(astring): return
>>   Required arguments:
>>     astring : input string(len=10)
>>
>>
>> PS: I am not sure where the ending 'E' comes from, I'll look into it..
>>
>> HTH,
>> Pearu
>>
>>
>>
>> On Fri, Oct 15, 2010 at 10:43 PM, Mark Oberfield
>> <[email protected]> wrote:
>> > Hi,
>> >
>> > What I am attempting to do with f2py is to have a FORTRAN77 subroutine
>> > call a Python function.  The f2py tutorial/documentation provides an
>> > simple example of this, but what I want to do is a little more
>> > elaborate and I running into problems. First, the description of the
>> > puzzle.
>> >
>> > I have three FORTRAN routines, "A","B" & "C".  I have source code for
>> > routines "A" and "C" and I can change them to accomplish my task.
>> >
>> > Subroutine A was originally "PROGRAM A" but now will be called from
>> > Python while I pass the Python routine, 'pyfunction', that I want to
>> > be executed.
>> >
>> > I cannot modify the B Subroutine; please consider it to be inside a
>> > library for which I don't have the source code.
>> >
>> > Subroutine "C" is where I want to execute the Python routine. So the
>> > execution stack looks something like this:
>> >
>> > python=>A=>B=>C=>pyfunction
>> >
>> > Since function names are not allowed in FORTRAN common blocks, I wrote
>> > simple "C" routines to store and execute the function pointer when
>> > called from FORTRAN.  I would think this would work but I get an error.
>> >
>> > Here are the routines:
>> >
>> >      SUBROUTINE A(PYFUNCTION)
>> >      CHARACTER*10 ASTRING
>> >      CALL RGSTR_FUNCTION(PYFUNCTION)
>> >      ASTRING = ' '
>> >      CALL B(ASTRING)
>> >      PRINT *, ASTRING
>> >      RETURN
>> >      END
>> >
>> >      SUBROUTINE B(ASTRING)
>> >      C
>> >      C Cannot change this routine
>> >      C
>> >      CHARACTER*10 ASTRING
>> >      CALL C(ASTRING)
>> >      RETURN
>> >      END
>> >
>> >      SUBROUTINE C(ASTRING)
>> >      CHARACTER*10 ASTRING
>> >      CALL RUN_PYTHON(ASTRING)
>> >      RETURN
>> >      END
>> >
>> > c2py.c:
>> >        /*
>> >         * Declare a private static variable, a function pointer
>> which is a
>> >         * Python routine
>> >         */
>> >        static void (*python_function)(char*);
>> >
>> >        void rgstr_function(void *fptr)
>> >        {
>> >           python_function = (void(*)(char*))fptr;
>> >        }
>> >
>> >        void run_python(char *astring)
>> >        {
>> >           (*python_function)(astring);
>> >        }
>> >
>> > I build it okay:
>> >
>> > f2py -c --f77flags=-qextname=a:b:c -m fmodule a.f b.f c.f c2py.c
>> >
>> > and fmodule.so gets built.
>> >
>> > Python 2.7 (r27:82500, Sep 20 2010, 13:40:19) [C] on aix5
>> > Type "help", "copyright", "credits" or "license" for more information.
>> >>>> import numpy
>> >>>> import fmodule
>> >>>> def simple():
>> > ...    return 'Hi there!'
>> > ...
>> >>>> fmodule.a(simple)
>> > Traceback (most recent call last):
>> >  File "<stdin>", line 1, in <module>
>> > TypeError: fmodule.a() 1st argument (pyfunction) can't be converted
>> to float
>> >
>> > So I change "A" to specify that PYFUNCTION is a function:
>> >
>> >      SUBROUTINE A(PYFUNCTION)
>> >      EXTERNAL PYFUNCTION
>> >      CHARACTER*10 ASTRING
>> >      ASTRING = ' '
>> >      CALL RGSTR_FUNCTION(PYFUNCTION)
>> >      CALL B(ASTRING)
>> >      PRINT *, ASTRING
>> >      RETURN
>> >      END
>> >
>> > When I attempt to rebuild fmodule.so I get errors like this:
>> >
>> > "/tmp/tmpLEJzd5/src.aix-5.3-2.7/fmodulemodule.c", line 357.22:
>> 1506-275 (S) Unexpected text pyfunction_cptr encountered.
>> > "/tmp/tmpLEJzd5/src.aix-5.3-2.7/fmodulemodule.c", line 357.3:
>> 1506-045 (S) Undeclared identifier pyfunction_typedef.
>> > "/tmp/tmpLEJzd5/src.aix-5.3-2.7/fmodulemodule.c", line 371.3:
>> 1506-045 (S) Undeclared identifier pyfunction_cptr.
>> >
>> > And fmodule.so does not get built.
>> >
>> > I am hoping that someone has done something similar and can pass on
>> > their wisdom.  Is this the right approach?  Is it even possible? If
>> > so, is there an easier way to accomplish this kind of task?
>> >
>> > Any advice or a solution would be most appreciated.
>> >
>> > Thanks!
>> >
>> > Mark
>> > --
>> > "A mother takes twenty years to make a man of her boy, and another
>> > woman makes a fool of him in twenty minutes."
>> >        -- Anonymous
>> >
>> > _______________________________________________
>> > f2py-users mailing list
>> > f2py-users-Y4l6ocDipWCuvFJfX82//[email protected]
>> >
>> >
>>
>> _______________________________________________
>> f2py-users mailing list
>> f2py-users-Y4l6ocDipWCuvFJfX82//[email protected]
>>
>
> _______________________________________________
> f2py-users mailing list
> f2py-users-Y4l6ocDipWCuvFJfX82//[email protected]
> http://cens.ioc.ee/mailman/listinfo/f2py-users
>