From: Berend de B. <be...@po...> - 2007-11-15 23:01:24
Attachments:
smime.p7s
|
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 !=3D NULL ) { temp =3D signal_switch; signal_switch =3D NULL; eif_unfreeze (frozen_signal_switch); frozen_signal_switch =3D NULL; eif_wean (temp); } if ( a_switch !=3D NULL ) { tid =3D eif_type_id ("STDC_SIGNAL_SWITCH"); signal_callback =3D eif_procedure ("switcher", tid); if (signal_callback =3D=3D 0) { eif_panic ("switcher feature not found."); } frozen_signal_switch =3D eif_freeze (a_switch); signal_switch =3D 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. =2D-=20 Cheers, Berend de Boer |
From: Emmanuel S. [ES] <ma...@ei...> - 2007-11-15 23:36:01
|
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: gob...@li... > [mailto:gob...@li...] 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 > |
From: Berend de B. <be...@po...> - 2008-04-16 11:02:35
Attachments:
smime.p7s
|
>>>>> "Emmanuel" == Emmanuel Stapf [ES] <ma...@ei...> 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 |
From: Eric B. <er...@go...> - 2007-11-16 14:44:42
|
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:er...@go... 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: gob...@li... >> [mailto:gob...@li...] 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 >> |
From: Berend de B. <be...@po...> - 2008-04-16 11:16:16
Attachments:
smime.p7s
|
>>>>> "Eric" == Eric Bezault <er...@go...> 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 |
From: Berend de B. <be...@po...> - 2008-04-16 11:19:53
Attachments:
smime.p7s
|
>>>>> "Berend" == Berend de Boer <be...@po...> 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 |
From: Eric B. <er...@go...> - 2008-04-16 12:00:21
|
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:er...@go... http://www.gobosoft.com |
From: Jocelyn <li...@dj...> - 2008-04-16 12:07:12
|
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? > > |
From: Berend de B. <be...@po...> - 2008-04-16 19:12:35
Attachments:
smime.p7s
|
>>>>> "Eric" == Eric Bezault <er...@go...> 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 |