Callback from C to Eiffel

9 Messages Forum Options Options
Permalink
Berend de Boer
Callback from C to Eiffel
Reply Threaded More
Print post
Permalink
Hi Eric,

Can I callback from C to Eiffel? Need this at a few places in eposix,
for example to support signals.

For example this the code used for ISE:

  EIF_TYPE_ID tid;
  EIF_OBJECT temp;
  if ( signal_switch != NULL ) {
    temp = signal_switch;
    signal_switch = NULL;
    eif_unfreeze (frozen_signal_switch);
    frozen_signal_switch = NULL;
    eif_wean (temp);
  }
  if ( a_switch != NULL ) {
    tid = eif_type_id ("STDC_SIGNAL_SWITCH");
    signal_callback = eif_procedure ("switcher", tid);
    if (signal_callback == 0)
      { eif_panic ("switcher feature not found."); }
    frozen_signal_switch = eif_freeze (a_switch);
    signal_switch = eif_adopt (a_switch);
  }

I.e. the callback pointer is "calculated" at set time and stored in
signal_switch. When a signal occurs, this call is made:

  (signal_callback) (frozen_signal_switch, sig);


SmartEiffel has a different strategy. When a feature is exported, SE
simply generates a prototype for it in the cecil.h file:

  /* Available Eiffel routines via -cecil:
  */
  void stdc_exit_switch_at_exit(void* C);
  void stdc_signal_switch_switcher(void* C,T2 a1);

And within C I can simply call stdc_signal_switch_switcher to make the
callback to Eiffel.

--
Cheers,

Berend de Boer


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
gobo-eiffel-develop mailing list
gobo-eiffel-develop@...
https://lists.sourceforge.net/lists/listinfo/gobo-eiffel-develop

smime.p7s (1K) Download Attachment
Emmanuel Stapf
Re: Callback from C to Eiffel
Reply Threaded More
Print post
Permalink
The easiest way for doing this kind of callback is to store the eiffel
routine address by doing:

c_set_address (p: POINTER) is
        external
                "C inline use <your.h>"
        alias
                "signal_callback = $p"
        end

where you do:

        c_set_address (your_eiffel_routine_callback)


To store the object needed for the call:

c_set_object (a: POINTER) is
        external
                "C inline use <your.h>"
        alias
                "signal_object = eif_protect($a);"
        end

where you do:

        c_set_object ($Current) -- Current or any other entity

Then the C code should simply look like:

        (signal_callback) (eif_adopt(signal_object), sig)

That way there is no need to worry about freezing objects.

Manu

> -----Original Message-----
> From: gobo-eiffel-develop-bounces@...
> [mailto:gobo-eiffel-develop-bounces@...] On
> Behalf Of Berend de Boer
> Sent: Thursday, November 15, 2007 3:01 PM
> To: Gobo Developers Mailing List
> Subject: [gobo-eiffel-develop] Callback from C to Eiffel
>
> Hi Eric,
>
> Can I callback from C to Eiffel? Need this at a few places in
> eposix, for example to support signals.
>
> For example this the code used for ISE:
>
>   EIF_TYPE_ID tid;
>   EIF_OBJECT temp;
>   if ( signal_switch != NULL ) {
>     temp = signal_switch;
>     signal_switch = NULL;
>     eif_unfreeze (frozen_signal_switch);
>     frozen_signal_switch = NULL;
>     eif_wean (temp);
>   }
>   if ( a_switch != NULL ) {
>     tid = eif_type_id ("STDC_SIGNAL_SWITCH");
>     signal_callback = eif_procedure ("switcher", tid);
>     if (signal_callback == 0)
>       { eif_panic ("switcher feature not found."); }
>     frozen_signal_switch = eif_freeze (a_switch);
>     signal_switch = eif_adopt (a_switch);
>   }
>
> I.e. the callback pointer is "calculated" at set time and
> stored in signal_switch. When a signal occurs, this call is made:
>
>   (signal_callback) (frozen_signal_switch, sig);
>
>
> SmartEiffel has a different strategy. When a feature is
> exported, SE simply generates a prototype for it in the cecil.h file:
>
>   /* Available Eiffel routines via -cecil:
>   */
>   void stdc_exit_switch_at_exit(void* C);
>   void stdc_signal_switch_switcher(void* C,T2 a1);
>
> And within C I can simply call stdc_signal_switch_switcher to
> make the callback to Eiffel.
>
> --
> Cheers,
>
> Berend de Boer
>


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
gobo-eiffel-develop mailing list
gobo-eiffel-develop@...
https://lists.sourceforge.net/lists/listinfo/gobo-eiffel-develop
------------------------------------------------------------------------  
Eiffel Software
805-685-1006
http://www.eiffel.com       
Customer support: http://support.eiffel.com       
User group: http://groups.eiffel.com/join       
------------------------------------------------------------------------  
Eric Bezault
Re: Callback from C to Eiffel
Reply Threaded More
Print post
Permalink
I tend to agree with Manu. First, when calling Eiffel from C, I think
that we should make the difference between a C program which calls some
Eiffel code, and an Eiffel program which calls some C code which then
calls some Eiffel code. I think that the CECIL mechanism has been
designed for the first case. In the second case, Manu's example works
fine without using CECIL. I think that there is a typo though in Manu's
example:

 > c_set_address (your_eiffel_routine_callback)

should probably be:

  c_set_address ($your_eiffel_routine_callback)

Anyway, I prefer this technique better because the other one with
`eif_type_id' and `eif_procedure' has the drawback that we don't
get a compilation error when we rename the class or the feature.
And if I remember correctly, this technique of passing $feature_name
to the C side is what has already been used to implement Expat
callbacks in the XML library.

As for external features, you should note that gec also has a
limitation when passing $feature_name to the C side. If the
feature has non-expanded argument types then you may experience
some weird behavior. But with expanded arguments, it seems to
work. At least the example below works with gec under Windows:


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class FOO

create

        make

feature

        make is
                do
                        c_set_address ($f)
                        c_set_object ($Current)
                        foo_c
                end

        c_set_address (p: POINTER) is
                external
                        "C inline use <foo_c.h>"
                alias
                        "signal_callback = $p;"
                end

        c_set_object (a: POINTER) is
                external
                        "C inline use <foo_c.h>"
                alias
                        "signal_object = eif_protect($a);"
                end

        f (i: INTEGER) is
                do
                        print (i)
                end

        foo_c is
                external
                        "C"
                end

end
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#include "ge_eiffel.h"
#include "ge_gc.h"

extern EIF_REFERENCE signal_object;
extern void (*signal_callback)(EIF_REFERENCE, EIF_INTEGER_32);
extern void foo_c(Void);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#include "foo_c.h"

EIF_REFERENCE signal_object;
void (*signal_callback)(EIF_REFERENCE, EIF_INTEGER_32);

void foo_c()
{
        (signal_callback) (eif_adopt(signal_object), 1);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

--
Eric Bezault
mailto:ericb@...
http://www.gobosoft.com


Emmanuel Stapf [ES] wrote:

> The easiest way for doing this kind of callback is to store the eiffel
> routine address by doing:
>
> c_set_address (p: POINTER) is
> external
> "C inline use <your.h>"
> alias
> "signal_callback = $p"
> end
>
> where you do:
>
> c_set_address (your_eiffel_routine_callback)
>
>
> To store the object needed for the call:
>
> c_set_object (a: POINTER) is
> external
> "C inline use <your.h>"
> alias
> "signal_object = eif_protect($a);"
> end
>
> where you do:
>
> c_set_object ($Current) -- Current or any other entity
>
> Then the C code should simply look like:
>
> (signal_callback) (eif_adopt(signal_object), sig)
>
> That way there is no need to worry about freezing objects.
>
> Manu
>
>> -----Original Message-----
>> From: gobo-eiffel-develop-bounces@...
>> [mailto:gobo-eiffel-develop-bounces@...] On
>> Behalf Of Berend de Boer
>> Sent: Thursday, November 15, 2007 3:01 PM
>> To: Gobo Developers Mailing List
>> Subject: [gobo-eiffel-develop] Callback from C to Eiffel
>>
>> Hi Eric,
>>
>> Can I callback from C to Eiffel? Need this at a few places in
>> eposix, for example to support signals.
>>
>> For example this the code used for ISE:
>>
>>   EIF_TYPE_ID tid;
>>   EIF_OBJECT temp;
>>   if ( signal_switch != NULL ) {
>>     temp = signal_switch;
>>     signal_switch = NULL;
>>     eif_unfreeze (frozen_signal_switch);
>>     frozen_signal_switch = NULL;
>>     eif_wean (temp);
>>   }
>>   if ( a_switch != NULL ) {
>>     tid = eif_type_id ("STDC_SIGNAL_SWITCH");
>>     signal_callback = eif_procedure ("switcher", tid);
>>     if (signal_callback == 0)
>>       { eif_panic ("switcher feature not found."); }
>>     frozen_signal_switch = eif_freeze (a_switch);
>>     signal_switch = eif_adopt (a_switch);
>>   }
>>
>> I.e. the callback pointer is "calculated" at set time and
>> stored in signal_switch. When a signal occurs, this call is made:
>>
>>   (signal_callback) (frozen_signal_switch, sig);
>>
>>
>> SmartEiffel has a different strategy. When a feature is
>> exported, SE simply generates a prototype for it in the cecil.h file:
>>
>>   /* Available Eiffel routines via -cecil:
>>   */
>>   void stdc_exit_switch_at_exit(void* C);
>>   void stdc_signal_switch_switcher(void* C,T2 a1);
>>
>> And within C I can simply call stdc_signal_switch_switcher to
>> make the callback to Eiffel.
>>
>> --
>> Cheers,
>>
>> Berend de Boer
>>





-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
gobo-eiffel-develop mailing list
gobo-eiffel-develop@...
https://lists.sourceforge.net/lists/listinfo/gobo-eiffel-develop
Berend de Boer
Re: Callback from C to Eiffel
Reply Threaded More
Print post
Permalink
In reply to this post by Emmanuel Stapf
>>>>> "Emmanuel" == Emmanuel Stapf [ES] <manus@...> writes:

    Emmanuel> The easiest way for doing this kind of callback is to
    Emmanuel> store the eiffel routine address by doing:

Hi Emmanuel,

I finally had the time to test this, but I get a segment violation. I
used Eric's example which I included below. Here's my result:

 # ./project

 project: system execution failed.
 Following is the set of recorded exceptions:

 -------------------------------------------------------------------------------
 Class / Object      Routine                Nature of exception           Effect
 -------------------------------------------------------------------------------
 FOO                 foo_c                  Segmentation fault:          
 <00000000B79BC03C>                         Operating system signal.      Fail
 -------------------------------------------------------------------------------
 FOO                 foo_c                                              
 <00000000B79BC03C>                         Routine failure.              Fail
 -------------------------------------------------------------------------------
 FOO                 make @3                                            
 <00000000B79BC03C>                         Routine failure.              Fail
 -------------------------------------------------------------------------------
 FOO                 root's creation                                    
 <00000000B79BC03C>                         Routine failure.              Exit
 -------------------------------------------------------------------------------


When I add debug statements it appears the $Current simply is not
correct when going back from C to Eiffel. Inside Eiffel when doing
things like:

                        print ("Current: " + ($Current).out + "%N")

It is different from what it should be. I can print that when in
finalized mode as the executable doesn't dump then (but doesn't have the
correct Current of course). The output of print(i) is correct though. On
more complex examples where I need Current to be valid it simply doesn't
work.

Here is the output for a finalized system:

 Current: 0xB79D403C
 Current: 0xB7222298
 1FOO [0xB79D403C]
   me: STRING_8 [0xB79D423C]


Could you please have a look?

You obviously need to change the path in the .ecf file. Here's how I
compiled the object file:

  cc -c -I/usr/local/Eiffel61/studio/spec/linux-x86/include -o foo_c.o foo_c.c

Finally my estudio version is 6.1.7.1477.


Haven't tried this code with gec yet, first need Eiffel Studio to work
as I need a real gc for a big project.


=========================foo.e=========================
class FOO

create

        make

feature

        make is
                do
                        c_set_address ($f)
                        c_set_object ($Current)
                        print ("Current: " + ($Current).out + "%N")
                        me := "hello world"
                        foo_c
                end

        c_set_address (p: POINTER) is
                external
                        "C inline use <foo_c.h>"
                alias
                        "signal_callback = $p;"
                end

        c_set_object (a: POINTER) is
                external
                        "C inline use <foo_c.h>"
                alias
                        "signal_object = eif_protect($a);"
                end

        f (i: INTEGER) is
                do
                        print ("Current: " + ($Current).out + "%N")
                        print (i)
                        print (me)
                end

        me: STRING

        foo_c is
                external
                        "C"
                end

end
==================================================


=========================foo_c.h=========================
//#include "ge_eiffel.h"
//#include "ge_gc.h"
#include <eif_portable.h>
#include <eif_hector.h>
#include <eif_macros.h>

extern EIF_REFERENCE signal_object;
extern void (*signal_callback)(EIF_REFERENCE, EIF_INTEGER_32);
extern void foo_c(Void);
==================================================


=========================foo_c.c=========================
#include "foo_c.h"

EIF_REFERENCE signal_object;
void (*signal_callback)(EIF_REFERENCE, EIF_INTEGER_32);

void foo_c()
{
        (signal_callback) (eif_adopt(signal_object), 1);
}
==================================================


=========================project.ecf=========================
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-3-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-3-0 http://www.eiffel.com/developers/xml/configuration-1-3-0.xsd" name="project" uuid="D9168F8A-7E13-4E12-92A4-EC3FDCE24B6E">
        <target name="project">
                <root class="FOO" feature="make"/>
                <option warning="true">
                        <assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
                </option>
                <external_include location="/home/berend/src/test/eiffel_signal_callback/"/>
                <external_object location="/home/berend/src/test/eiffel_signal_callback/foo_c.o"/>
                <precompile name="base_pre" location="$ISE_PRECOMP\base.ecf"/>
                <library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
                <cluster name="project" location=".\" recursive="true">
                        <file_rule>
                                <exclude>/EIFGENs$</exclude>
                                <exclude>/.svn$</exclude>
                                <exclude>/CVS$</exclude>
                        </file_rule>
                </cluster>
        </target>
        <target name="project_dotnet" extends="project">
                <setting name="msil_generation" value="true"/>
        </target>
</system>
==================================================


--
Live long and prosper,

Berend de Boer


-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference
Don't miss this year's exciting event. There's still time to save $100.
Use priority code J8TL2D2.
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
gobo-eiffel-develop mailing list
gobo-eiffel-develop@...
https://lists.sourceforge.net/lists/listinfo/gobo-eiffel-develop

smime.p7s (1K) Download Attachment
Berend de Boer
Re: Callback from C to Eiffel
Reply Threaded More
Print post
Permalink
In reply to this post by Eric Bezault
>>>>> "Eric" == Eric Bezault <ericb@...> writes:

    Eric> I tend to agree with Manu. First, when calling Eiffel from C,
    Eric> I think that we should make the difference between a C program
    Eric> which calls some Eiffel code, and an Eiffel program which
    Eric> calls some C code which then calls some Eiffel code. I think
    Eric> that the CECIL mechanism has been designed for the first
    Eric> case. In the second case, Manu's example works fine without
    Eric> using CECIL.

Just did a quick test and the code works beautifully with gec (not the
example code, but the actual project actually!). But with EiffelStudio I
have the problems as indicated.

--
Cheers,

Berend de Boer


-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference
Don't miss this year's exciting event. There's still time to save $100.
Use priority code J8TL2D2.
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
gobo-eiffel-develop mailing list
gobo-eiffel-develop@...
https://lists.sourceforge.net/lists/listinfo/gobo-eiffel-develop

smime.p7s (1K) Download Attachment
Berend de Boer
Re: Callback from C to Eiffel
Reply Threaded More
Print post
Permalink
>>>>> "Berend" == Berend de Boer <berend@...> writes:

    Berend> Just did a quick test and the code works beautifully with
    Berend> gec (not the example code, but the actual project
    Berend> actually!).

Sorry this is unclear. Didn't try the sample code, went straight to the
project, and it worked perfectly under gec. Now only if gec had a moving
garbage collector...

--
Cheers

Berend de Boer


-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference
Don't miss this year's exciting event. There's still time to save $100.
Use priority code J8TL2D2.
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
gobo-eiffel-develop mailing list
gobo-eiffel-develop@...
https://lists.sourceforge.net/lists/listinfo/gobo-eiffel-develop

smime.p7s (1K) Download Attachment
Eric Bezault
Re: Callback from C to Eiffel
Reply Threaded More
Print post
Permalink
In reply to this post by Berend de Boer
Berend de Boer wrote:

> =========================foo_c.c=========================
> #include "foo_c.h"
>
> EIF_REFERENCE signal_object;
> void (*signal_callback)(EIF_REFERENCE, EIF_INTEGER_32);
>
> void foo_c()
> {
> (signal_callback) (eif_adopt(signal_object), 1);
> }

My guess is that you should use `eif_access' (and not
`eif_adopt'). Manu, can you confirm?

--
Eric Bezault
mailto:ericb@...
http://www.gobosoft.com

-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference
Don't miss this year's exciting event. There's still time to save $100.
Use priority code J8TL2D2.
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
gobo-eiffel-develop mailing list
gobo-eiffel-develop@...
https://lists.sourceforge.net/lists/listinfo/gobo-eiffel-develop
jocelyn-2
Re: Callback from C to Eiffel
Reply Threaded More
Print post
Permalink
You might be interested in the article on Eiffelroom:
http://www.eiffelroom.com/article/protecting_objects
And my guess is also that you should use eif_access.

-- Jocelyn

On 4/16/2008 14:00 PM, Eric Bezault wrote:

> Berend de Boer wrote:
>  
>> =========================foo_c.c=========================
>> #include "foo_c.h"
>>
>> EIF_REFERENCE signal_object;
>> void (*signal_callback)(EIF_REFERENCE, EIF_INTEGER_32);
>>
>> void foo_c()
>> {
>> (signal_callback) (eif_adopt(signal_object), 1);
>> }
>>    
>
> My guess is that you should use `eif_access' (and not
> `eif_adopt'). Manu, can you confirm?
>
>  



-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference
Don't miss this year's exciting event. There's still time to save $100.
Use priority code J8TL2D2.
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
gobo-eiffel-develop mailing list
gobo-eiffel-develop@...
https://lists.sourceforge.net/lists/listinfo/gobo-eiffel-develop
Berend de Boer
Re: Callback from C to Eiffel
Reply Threaded More
Print post
Permalink
In reply to this post by Eric Bezault
>>>>> "Eric" == Eric Bezault <ericb@...> writes:

    Eric> My guess is that you should use `eif_access' (and not
    Eric> `eif_adopt'). Manu, can you confirm?

Ah, brilliant tip. I can confirm this works, at least on a more complex
project Current is valid.

--
Cheers,

Berend de Boer


-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference
Don't miss this year's exciting event. There's still time to save $100.
Use priority code J8TL2D2.
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
gobo-eiffel-develop mailing list
gobo-eiffel-develop@...
https://lists.sourceforge.net/lists/listinfo/gobo-eiffel-develop

smime.p7s (1K) Download Attachment