Problem creating bindings for HaXe/Neko

classic Classic list List threaded Threaded
17 messages Options
Reply | Threaded
Open this post in threaded view
|

Problem creating bindings for HaXe/Neko

Simon TRENY
Hi,


I'm having a problem with creating haXe bindings for an existing
library I have written in C. Here is a simple function of the API I'd
like to bind:
Widget *widget_parent_get(Widget *widget); //Get the widget's parent


I'd like to bind it into something like this:
class Widget
{
   public function getParent() : Widget;
}


To do that, I've first created the following function in the code of the
.ndll:
value ndll_widget_parent_get(value widget)
{
   val_check_kind(widget, k_widget);
   return alloc_abstract(k_widget, widget_parent_get(val_data(widget)));
}


And then, the following haXe code:
class Widget
{
   private var abstract : Void;

   public function getParent() : Widget
   {
      var parent = new Widget();
      parent.abstract = _getParent(this.abstract);
      return parent;
   }

   static var _getParent = neko.Lib.load("",ndll_widget_parent_get,1);
}


So this code is working, but it has some serious problems:

1 - Each I'll call widget.getParent(), the ndll will allocate a new
abstract value containing the parent address, and then the haXe code
will allocate a new Widget containing the abstract. So it will result
in a lot of allocations just in order to access the parent of the
widget.

2 - Since each call to widget.getParent() will create a new object, I
won't be able to write things like this:
if (widget1.getParent() == widget2.getParent()) to test if two widgets
have the same parent.


Is there a better way to bind this function that solves these problems?

Thanks,
Simon

--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Problem creating bindings for HaXe/Neko

Nicolas Cannasse
Simon TRENY a écrit :
> Hi,
>
>
> I'm having a problem with creating haXe bindings for an existing
> library I have written in C. Here is a simple function of the API I'd
> like to bind:
> Widget *widget_parent_get(Widget *widget); //Get the widget's parent
[...]
> Is there a better way to bind this function that solves these problems?

Yes, that's a common problem when adding two levels of abstraction.
First, I hope that you can bind a void* to your Widget (as a "custom"
value). In that case, use an alloc_root(1) and for each widget, store
the corresponding abstract value. In case the Widget get destroyed, you
can use free_root + set the abstract kind to NULL, which will prevent
any further api calls on this widget.

Now that you have a strong abstract <-> widget binding, allocating an
object everytime is not a big problem, except for ==. In that case - and
only for neko - you can define the __compare method that will
compare two objects abstracts.

For instance :

private function __compare( w : Widget ) {
        return untyped __dollar__compare( abstract, w.abstract );
}

Best,
Nicolas

--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Problem creating bindings for HaXe/Neko

Lee Sylvester
I have this same problem, except a) I don't have a custom void* support
on my widgets, and b) I've dealt with this enough times to know better
;-)  I guess it's down to the ol' lookup tables :'-(

Lee



Nicolas Cannasse wrote:

> Simon TRENY a écrit :
>> Hi,
>>
>>
>> I'm having a problem with creating haXe bindings for an existing
>> library I have written in C. Here is a simple function of the API I'd
>> like to bind:
>> Widget *widget_parent_get(Widget *widget); //Get the widget's parent
> [...]
>> Is there a better way to bind this function that solves these problems?
>
> Yes, that's a common problem when adding two levels of abstraction.
> First, I hope that you can bind a void* to your Widget (as a "custom"
> value). In that case, use an alloc_root(1) and for each widget, store
> the corresponding abstract value. In case the Widget get destroyed,
> you can use free_root + set the abstract kind to NULL, which will
> prevent any further api calls on this widget.
>
> Now that you have a strong abstract <-> widget binding, allocating an
> object everytime is not a big problem, except for ==. In that case -
> and only for neko - you can define the __compare method that will
> compare two objects abstracts.
>
> For instance :
>
> private function __compare( w : Widget ) {
>     return untyped __dollar__compare( abstract, w.abstract );
> }
>
> Best,
> Nicolas
>


--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Problem creating bindings for HaXe/Neko

Simon TRENY
In reply to this post by Nicolas Cannasse
On Tue, 11 Nov 2008 18:24:39 +0100,
Nicolas Cannasse <[hidden email]> wrote :

> Simon TRENY a écrit :
> > Hi,
> >
> >
> > I'm having a problem with creating haXe bindings for an existing
> > library I have written in C. Here is a simple function of the API
> > I'd like to bind:
> > Widget *widget_parent_get(Widget *widget); //Get the widget's parent
> [...]
> > Is there a better way to bind this function that solves these
> > problems?
>
> Yes, that's a common problem when adding two levels of abstraction.
> First, I hope that you can bind a void* to your Widget (as a "custom"
> value). In that case, use an alloc_root(1) and for each widget, store
> the corresponding abstract value. In case the Widget get destroyed,
> you can use free_root + set the abstract kind to NULL, which will
> prevent any further api calls on this widget.
Ok, thanks, adding a void * to the structure won't be a problem.
But there is one thing I don't understand with this solution: if I call
alloc_root() on the abstract, won't it prevent the widget to be
garbage-collected? For now, i use a finalizer on the abstract, and in
the finalizer, I destroy the associated widget. This way, I can destroy
the widget when it is no longer referenced. Would this still work with
this solution?

>
> Now that you have a strong abstract <-> widget binding, allocating an
> object everytime is not a big problem, except for ==. In that case -
> and only for neko - you can define the __compare method that will
> compare two objects abstracts.
>
> For instance :
>
> private function __compare( w : Widget ) {
> return untyped __dollar__compare( abstract, w.abstract );
> }
Ok, that will work great, neko is the only target! :)

But, to avoid the allocating the object each time, wouldn't it be
possible to use a hash-table indexed by the abstract? It would require
the abstract to be hashable and comparable though. I don't know if
it's possible? And what would be more efficient: allocating each time,
or using the hash-table approach?


Thanks for your help :)
Simon

--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Problem creating bindings for HaXe/Neko

Lee Sylvester
You don't use the alloc_root on the widget, you use it on the item you'd
add to void*. This way, the memory is reserved and won't be overwritten.
The widget gets handled (partially) through alloc_abstract, though you
still need to be careful of how your memory is being cleaned / reused.
I'm guessing you've already thought about that in your library, though ;-)

Lee




Simon TRENY wrote:

> On Tue, 11 Nov 2008 18:24:39 +0100,
> Nicolas Cannasse <[hidden email]> wrote :
>
>  
>> Simon TRENY a écrit :
>>    
>>> Hi,
>>>
>>>
>>> I'm having a problem with creating haXe bindings for an existing
>>> library I have written in C. Here is a simple function of the API
>>> I'd like to bind:
>>> Widget *widget_parent_get(Widget *widget); //Get the widget's parent
>>>      
>> [...]
>>    
>>> Is there a better way to bind this function that solves these
>>> problems?
>>>      
>> Yes, that's a common problem when adding two levels of abstraction.
>> First, I hope that you can bind a void* to your Widget (as a "custom"
>> value). In that case, use an alloc_root(1) and for each widget, store
>> the corresponding abstract value. In case the Widget get destroyed,
>> you can use free_root + set the abstract kind to NULL, which will
>> prevent any further api calls on this widget.
>>    
> Ok, thanks, adding a void * to the structure won't be a problem.
> But there is one thing I don't understand with this solution: if I call
> alloc_root() on the abstract, won't it prevent the widget to be
> garbage-collected? For now, i use a finalizer on the abstract, and in
> the finalizer, I destroy the associated widget. This way, I can destroy
> the widget when it is no longer referenced. Would this still work with
> this solution?
>
>  
>> Now that you have a strong abstract <-> widget binding, allocating an
>> object everytime is not a big problem, except for ==. In that case -
>> and only for neko - you can define the __compare method that will
>> compare two objects abstracts.
>>
>> For instance :
>>
>> private function __compare( w : Widget ) {
>> return untyped __dollar__compare( abstract, w.abstract );
>> }
>>    
> Ok, that will work great, neko is the only target! :)
>
> But, to avoid the allocating the object each time, wouldn't it be
> possible to use a hash-table indexed by the abstract? It would require
> the abstract to be hashable and comparable though. I don't know if
> it's possible? And what would be more efficient: allocating each time,
> or using the hash-table approach?
>
>
> Thanks for your help :)
> Simon
>
>  


--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Problem creating bindings for HaXe/Neko

Lee Sylvester
I guess this needs elaboration... Okay..

Imagine I have a widget, and that widget can call a custom method with
the signature

void* myButtonCallback( myEvent* event );

Now, the problem is, I can't create a method like that in haXe, because
all my methods accept type value and return type value... Even null is
of type value. Ergo, what I do is create a standard method to handle all
my widget events, but have that method call a custom function for that
widget. Ergo:

void* myButtonCallback( myEvent* event )
{
    value func = (value) *myEvent->customHaXeFunctionValue;
    val_call1( func, alloc_int( myEvent->buttonId ) );
}

Now, when creating my widget, I simply provide a method that will allow
people to assign a handler method to that widget, but use alloc_root()
to handle the reservation of memory

value addWidgetClickHandler( value widget, value handler )
{
    value* func;
    val_check( widget, kind_buttonwidget );
    val_check_function( handler, 0 );
    func = alloc_root( 1 );
    *func = handler;
    ButtonWidget buttwedge = val_data( widget );
    buttwedge.custom = func;
}

There. That should do it, though I've not tested it, so there may be
typos ;-)  I've done this loads, myself, and it works a treat. The good
thing is, you get to assign a custom function to each widget without
breaking your old code, and without providing any *magic* ;-)

Lee




Lee McColl Sylvester wrote:

> You don't use the alloc_root on the widget, you use it on the item
> you'd add to void*. This way, the memory is reserved and won't be
> overwritten. The widget gets handled (partially) through
> alloc_abstract, though you still need to be careful of how your memory
> is being cleaned / reused. I'm guessing you've already thought about
> that in your library, though ;-)
>
> Lee
>
>
>
>
> Simon TRENY wrote:
>> On Tue, 11 Nov 2008 18:24:39 +0100,
>> Nicolas Cannasse <[hidden email]> wrote :
>>
>>  
>>> Simon TRENY a écrit :
>>>    
>>>> Hi,
>>>>
>>>>
>>>> I'm having a problem with creating haXe bindings for an existing
>>>> library I have written in C. Here is a simple function of the API
>>>> I'd like to bind:
>>>> Widget *widget_parent_get(Widget *widget); //Get the widget's parent
>>>>      
>>> [...]
>>>    
>>>> Is there a better way to bind this function that solves these
>>>> problems?
>>>>      
>>> Yes, that's a common problem when adding two levels of abstraction.
>>> First, I hope that you can bind a void* to your Widget (as a
>>> "custom" value). In that case, use an alloc_root(1) and for each
>>> widget, store the corresponding abstract value. In case the Widget
>>> get destroyed,
>>> you can use free_root + set the abstract kind to NULL, which will
>>> prevent any further api calls on this widget.
>>>    
>> Ok, thanks, adding a void * to the structure won't be a problem.
>> But there is one thing I don't understand with this solution: if I call
>> alloc_root() on the abstract, won't it prevent the widget to be
>> garbage-collected? For now, i use a finalizer on the abstract, and in
>> the finalizer, I destroy the associated widget. This way, I can destroy
>> the widget when it is no longer referenced. Would this still work with
>> this solution?
>>
>>  
>>> Now that you have a strong abstract <-> widget binding, allocating
>>> an object everytime is not a big problem, except for ==. In that case -
>>> and only for neko - you can define the __compare method that will
>>> compare two objects abstracts.
>>>
>>> For instance :
>>>
>>> private function __compare( w : Widget ) {
>>>     return untyped __dollar__compare( abstract, w.abstract );
>>> }
>>>    
>> Ok, that will work great, neko is the only target! :)
>>
>> But, to avoid the allocating the object each time, wouldn't it be
>> possible to use a hash-table indexed by the abstract? It would require
>> the abstract to be hashable and comparable though. I don't know if
>> it's possible? And what would be more efficient: allocating each time,
>> or using the hash-table approach?
>>
>>
>> Thanks for your help :)
>> Simon
>>
>>  
>
>


--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Problem creating bindings for HaXe/Neko

Simon TRENY
Thanks for the explanation! :)

Actually, I have already used the same system to add an "onTouchDown"
and an "onTouchUp" callback to the widget, so the user can do special
action when a widget is clicked, and it works indeed pretty well.

But the thing I don't understand is, if I use alloc_root(1) and I store
the abstract-value in it, the abstract value will always be referenced
(since it's will appear as a root-value for the GC), so it will
never be garbage-collected and I won't be able to know when the
widget-object is destroyed. Or maybe I'm missing something?

Regards,
Simon


On Tue, 11 Nov 2008 18:34:37 +0000,
Lee McColl Sylvester <[hidden email]> wrote :

> I guess this needs elaboration... Okay..
>
> Imagine I have a widget, and that widget can call a custom method
> with the signature
>
> void* myButtonCallback( myEvent* event );
>
> Now, the problem is, I can't create a method like that in haXe,
> because all my methods accept type value and return type value...
> Even null is of type value. Ergo, what I do is create a standard
> method to handle all my widget events, but have that method call a
> custom function for that widget. Ergo:
>
> void* myButtonCallback( myEvent* event )
> {
>     value func = (value) *myEvent->customHaXeFunctionValue;
>     val_call1( func, alloc_int( myEvent->buttonId ) );
> }
>
> Now, when creating my widget, I simply provide a method that will
> allow people to assign a handler method to that widget, but use
> alloc_root() to handle the reservation of memory
>
> value addWidgetClickHandler( value widget, value handler )
> {
>     value* func;
>     val_check( widget, kind_buttonwidget );
>     val_check_function( handler, 0 );
>     func = alloc_root( 1 );
>     *func = handler;
>     ButtonWidget buttwedge = val_data( widget );
>     buttwedge.custom = func;
> }
>
> There. That should do it, though I've not tested it, so there may be
> typos ;-)  I've done this loads, myself, and it works a treat. The
> good thing is, you get to assign a custom function to each widget
> without breaking your old code, and without providing any *magic* ;-)
>
> Lee
>
>
>
>
> Lee McColl Sylvester wrote:
> > You don't use the alloc_root on the widget, you use it on the item
> > you'd add to void*. This way, the memory is reserved and won't be
> > overwritten. The widget gets handled (partially) through
> > alloc_abstract, though you still need to be careful of how your
> > memory is being cleaned / reused. I'm guessing you've already
> > thought about that in your library, though ;-)
> >
> > Lee
> >
> >
> >
> >
> > Simon TRENY wrote:
> >> On Tue, 11 Nov 2008 18:24:39 +0100,
> >> Nicolas Cannasse <[hidden email]> wrote :
> >>
> >>  
> >>> Simon TRENY a écrit :
> >>>    
> >>>> Hi,
> >>>>
> >>>>
> >>>> I'm having a problem with creating haXe bindings for an existing
> >>>> library I have written in C. Here is a simple function of the API
> >>>> I'd like to bind:
> >>>> Widget *widget_parent_get(Widget *widget); //Get the widget's
> >>>> parent
> >>> [...]
> >>>    
> >>>> Is there a better way to bind this function that solves these
> >>>> problems?
> >>>>      
> >>> Yes, that's a common problem when adding two levels of
> >>> abstraction. First, I hope that you can bind a void* to your
> >>> Widget (as a "custom" value). In that case, use an alloc_root(1)
> >>> and for each widget, store the corresponding abstract value. In
> >>> case the Widget get destroyed,
> >>> you can use free_root + set the abstract kind to NULL, which will
> >>> prevent any further api calls on this widget.
> >>>    
> >> Ok, thanks, adding a void * to the structure won't be a problem.
> >> But there is one thing I don't understand with this solution: if I
> >> call alloc_root() on the abstract, won't it prevent the widget to
> >> be garbage-collected? For now, i use a finalizer on the abstract,
> >> and in the finalizer, I destroy the associated widget. This way, I
> >> can destroy the widget when it is no longer referenced. Would this
> >> still work with this solution?
> >>
> >>  
> >>> Now that you have a strong abstract <-> widget binding,
> >>> allocating an object everytime is not a big problem, except for
> >>> ==. In that case - and only for neko - you can define the
> >>> __compare method that will compare two objects abstracts.
> >>>
> >>> For instance :
> >>>
> >>> private function __compare( w : Widget ) {
> >>>     return untyped __dollar__compare( abstract, w.abstract );
> >>> }
> >>>    
> >> Ok, that will work great, neko is the only target! :)
> >>
> >> But, to avoid the allocating the object each time, wouldn't it be
> >> possible to use a hash-table indexed by the abstract? It would
> >> require the abstract to be hashable and comparable though. I don't
> >> know if it's possible? And what would be more efficient:
> >> allocating each time, or using the hash-table approach?
> >>
> >>
> >> Thanks for your help :)
> >> Simon
> >>
> >>  
> >
> >
>
>

--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Problem creating bindings for HaXe/Neko

Lee Sylvester
Ahh, I see what you're saying. You've got it reversed. What would
normally happen is you'd dispose of your widget, then in the widgets
destructor, you'd do something like :

void* ~ButtonWidget()
{
    alloc_free( customValue );
}

Or, if you're calling it externally,

value dispose( value widget )
{
    alloc_free( val_data( widget )->customValue );
}

Then, you just make sure you call this before disposing of your object
in haXe.

Lee





Simon TRENY wrote:

> Thanks for the explanation! :)
>
> Actually, I have already used the same system to add an "onTouchDown"
> and an "onTouchUp" callback to the widget, so the user can do special
> action when a widget is clicked, and it works indeed pretty well.
>
> But the thing I don't understand is, if I use alloc_root(1) and I store
> the abstract-value in it, the abstract value will always be referenced
> (since it's will appear as a root-value for the GC), so it will
> never be garbage-collected and I won't be able to know when the
> widget-object is destroyed. Or maybe I'm missing something?
>
> Regards,
> Simon
>
>
> On Tue, 11 Nov 2008 18:34:37 +0000,
> Lee McColl Sylvester <[hidden email]> wrote :
>
>  
>> I guess this needs elaboration... Okay..
>>
>> Imagine I have a widget, and that widget can call a custom method
>> with the signature
>>
>> void* myButtonCallback( myEvent* event );
>>
>> Now, the problem is, I can't create a method like that in haXe,
>> because all my methods accept type value and return type value...
>> Even null is of type value. Ergo, what I do is create a standard
>> method to handle all my widget events, but have that method call a
>> custom function for that widget. Ergo:
>>
>> void* myButtonCallback( myEvent* event )
>> {
>>     value func = (value) *myEvent->customHaXeFunctionValue;
>>     val_call1( func, alloc_int( myEvent->buttonId ) );
>> }
>>
>> Now, when creating my widget, I simply provide a method that will
>> allow people to assign a handler method to that widget, but use
>> alloc_root() to handle the reservation of memory
>>
>> value addWidgetClickHandler( value widget, value handler )
>> {
>>     value* func;
>>     val_check( widget, kind_buttonwidget );
>>     val_check_function( handler, 0 );
>>     func = alloc_root( 1 );
>>     *func = handler;
>>     ButtonWidget buttwedge = val_data( widget );
>>     buttwedge.custom = func;
>> }
>>
>> There. That should do it, though I've not tested it, so there may be
>> typos ;-)  I've done this loads, myself, and it works a treat. The
>> good thing is, you get to assign a custom function to each widget
>> without breaking your old code, and without providing any *magic* ;-)
>>
>> Lee
>>
>>
>>
>>
>> Lee McColl Sylvester wrote:
>>    
>>> You don't use the alloc_root on the widget, you use it on the item
>>> you'd add to void*. This way, the memory is reserved and won't be
>>> overwritten. The widget gets handled (partially) through
>>> alloc_abstract, though you still need to be careful of how your
>>> memory is being cleaned / reused. I'm guessing you've already
>>> thought about that in your library, though ;-)
>>>
>>> Lee
>>>
>>>
>>>
>>>
>>> Simon TRENY wrote:
>>>      
>>>> On Tue, 11 Nov 2008 18:24:39 +0100,
>>>> Nicolas Cannasse <[hidden email]> wrote :
>>>>
>>>>  
>>>>        
>>>>> Simon TRENY a écrit :
>>>>>    
>>>>>          
>>>>>> Hi,
>>>>>>
>>>>>>
>>>>>> I'm having a problem with creating haXe bindings for an existing
>>>>>> library I have written in C. Here is a simple function of the API
>>>>>> I'd like to bind:
>>>>>> Widget *widget_parent_get(Widget *widget); //Get the widget's
>>>>>> parent
>>>>>>            
>>>>> [...]
>>>>>    
>>>>>          
>>>>>> Is there a better way to bind this function that solves these
>>>>>> problems?
>>>>>>      
>>>>>>            
>>>>> Yes, that's a common problem when adding two levels of
>>>>> abstraction. First, I hope that you can bind a void* to your
>>>>> Widget (as a "custom" value). In that case, use an alloc_root(1)
>>>>> and for each widget, store the corresponding abstract value. In
>>>>> case the Widget get destroyed,
>>>>> you can use free_root + set the abstract kind to NULL, which will
>>>>> prevent any further api calls on this widget.
>>>>>    
>>>>>          
>>>> Ok, thanks, adding a void * to the structure won't be a problem.
>>>> But there is one thing I don't understand with this solution: if I
>>>> call alloc_root() on the abstract, won't it prevent the widget to
>>>> be garbage-collected? For now, i use a finalizer on the abstract,
>>>> and in the finalizer, I destroy the associated widget. This way, I
>>>> can destroy the widget when it is no longer referenced. Would this
>>>> still work with this solution?
>>>>
>>>>  
>>>>        
>>>>> Now that you have a strong abstract <-> widget binding,
>>>>> allocating an object everytime is not a big problem, except for
>>>>> ==. In that case - and only for neko - you can define the
>>>>> __compare method that will compare two objects abstracts.
>>>>>
>>>>> For instance :
>>>>>
>>>>> private function __compare( w : Widget ) {
>>>>>     return untyped __dollar__compare( abstract, w.abstract );
>>>>> }
>>>>>    
>>>>>          
>>>> Ok, that will work great, neko is the only target! :)
>>>>
>>>> But, to avoid the allocating the object each time, wouldn't it be
>>>> possible to use a hash-table indexed by the abstract? It would
>>>> require the abstract to be hashable and comparable though. I don't
>>>> know if it's possible? And what would be more efficient:
>>>> allocating each time, or using the hash-table approach?
>>>>
>>>>
>>>> Thanks for your help :)
>>>> Simon
>>>>
>>>>  
>>>>        
>>>      
>>    
>
>  


--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Problem creating bindings for HaXe/Neko

Simon TRENY
Ok, thanks! :)

Now, how can I know when an object is destroyed by the
garbage-collector? I would need to know that in order to call the
"dispose" function to free the custom-value, right?

Simon


On Tue, 11 Nov 2008 19:43:56 +0000,
Lee McColl Sylvester <[hidden email]> wrote :

> Ahh, I see what you're saying. You've got it reversed. What would
> normally happen is you'd dispose of your widget, then in the widgets
> destructor, you'd do something like :
>
> void* ~ButtonWidget()
> {
>     alloc_free( customValue );
> }
>
> Or, if you're calling it externally,
>
> value dispose( value widget )
> {
>     alloc_free( val_data( widget )->customValue );
> }
>
> Then, you just make sure you call this before disposing of your
> object in haXe.
>
> Lee
>
>
>
>
>
> Simon TRENY wrote:
> > Thanks for the explanation! :)
> >
> > Actually, I have already used the same system to add an
> > "onTouchDown" and an "onTouchUp" callback to the widget, so the
> > user can do special action when a widget is clicked, and it works
> > indeed pretty well.
> >
> > But the thing I don't understand is, if I use alloc_root(1) and I
> > store the abstract-value in it, the abstract value will always be
> > referenced (since it's will appear as a root-value for the GC), so
> > it will never be garbage-collected and I won't be able to know when
> > the widget-object is destroyed. Or maybe I'm missing something?
> >
> > Regards,
> > Simon
> >
> >
> > On Tue, 11 Nov 2008 18:34:37 +0000,
> > Lee McColl Sylvester <[hidden email]> wrote :
> >
> >  
> >> I guess this needs elaboration... Okay..
> >>
> >> Imagine I have a widget, and that widget can call a custom method
> >> with the signature
> >>
> >> void* myButtonCallback( myEvent* event );
> >>
> >> Now, the problem is, I can't create a method like that in haXe,
> >> because all my methods accept type value and return type value...
> >> Even null is of type value. Ergo, what I do is create a standard
> >> method to handle all my widget events, but have that method call a
> >> custom function for that widget. Ergo:
> >>
> >> void* myButtonCallback( myEvent* event )
> >> {
> >>     value func = (value) *myEvent->customHaXeFunctionValue;
> >>     val_call1( func, alloc_int( myEvent->buttonId ) );
> >> }
> >>
> >> Now, when creating my widget, I simply provide a method that will
> >> allow people to assign a handler method to that widget, but use
> >> alloc_root() to handle the reservation of memory
> >>
> >> value addWidgetClickHandler( value widget, value handler )
> >> {
> >>     value* func;
> >>     val_check( widget, kind_buttonwidget );
> >>     val_check_function( handler, 0 );
> >>     func = alloc_root( 1 );
> >>     *func = handler;
> >>     ButtonWidget buttwedge = val_data( widget );
> >>     buttwedge.custom = func;
> >> }
> >>
> >> There. That should do it, though I've not tested it, so there may
> >> be typos ;-)  I've done this loads, myself, and it works a treat.
> >> The good thing is, you get to assign a custom function to each
> >> widget without breaking your old code, and without providing any
> >> *magic* ;-)
> >>
> >> Lee
> >>
> >>
> >>
> >>
> >> Lee McColl Sylvester wrote:
> >>    
> >>> You don't use the alloc_root on the widget, you use it on the
> >>> item you'd add to void*. This way, the memory is reserved and
> >>> won't be overwritten. The widget gets handled (partially) through
> >>> alloc_abstract, though you still need to be careful of how your
> >>> memory is being cleaned / reused. I'm guessing you've already
> >>> thought about that in your library, though ;-)
> >>>
> >>> Lee
> >>>
> >>>
> >>>
> >>>
> >>> Simon TRENY wrote:
> >>>      
> >>>> On Tue, 11 Nov 2008 18:24:39 +0100,
> >>>> Nicolas Cannasse <[hidden email]> wrote :
> >>>>
> >>>>  
> >>>>        
> >>>>> Simon TRENY a écrit :
> >>>>>    
> >>>>>          
> >>>>>> Hi,
> >>>>>>
> >>>>>>
> >>>>>> I'm having a problem with creating haXe bindings for an
> >>>>>> existing library I have written in C. Here is a simple
> >>>>>> function of the API I'd like to bind:
> >>>>>> Widget *widget_parent_get(Widget *widget); //Get the widget's
> >>>>>> parent
> >>>>>>            
> >>>>> [...]
> >>>>>    
> >>>>>          
> >>>>>> Is there a better way to bind this function that solves these
> >>>>>> problems?
> >>>>>>      
> >>>>>>            
> >>>>> Yes, that's a common problem when adding two levels of
> >>>>> abstraction. First, I hope that you can bind a void* to your
> >>>>> Widget (as a "custom" value). In that case, use an alloc_root(1)
> >>>>> and for each widget, store the corresponding abstract value. In
> >>>>> case the Widget get destroyed,
> >>>>> you can use free_root + set the abstract kind to NULL, which
> >>>>> will prevent any further api calls on this widget.
> >>>>>    
> >>>>>          
> >>>> Ok, thanks, adding a void * to the structure won't be a problem.
> >>>> But there is one thing I don't understand with this solution: if
> >>>> I call alloc_root() on the abstract, won't it prevent the widget
> >>>> to be garbage-collected? For now, i use a finalizer on the
> >>>> abstract, and in the finalizer, I destroy the associated widget.
> >>>> This way, I can destroy the widget when it is no longer
> >>>> referenced. Would this still work with this solution?
> >>>>
> >>>>  
> >>>>        
> >>>>> Now that you have a strong abstract <-> widget binding,
> >>>>> allocating an object everytime is not a big problem, except for
> >>>>> ==. In that case - and only for neko - you can define the
> >>>>> __compare method that will compare two objects abstracts.
> >>>>>
> >>>>> For instance :
> >>>>>
> >>>>> private function __compare( w : Widget ) {
> >>>>>     return untyped __dollar__compare( abstract, w.abstract );
> >>>>> }
> >>>>>    
> >>>>>          
> >>>> Ok, that will work great, neko is the only target! :)
> >>>>
> >>>> But, to avoid the allocating the object each time, wouldn't it be
> >>>> possible to use a hash-table indexed by the abstract? It would
> >>>> require the abstract to be hashable and comparable though. I
> >>>> don't know if it's possible? And what would be more efficient:
> >>>> allocating each time, or using the hash-table approach?
> >>>>
> >>>>
> >>>> Thanks for your help :)
> >>>> Simon
> >>>>
> >>>>  
> >>>>        
> >>>      
> >>    
> >
> >  
>
>

--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Problem creating bindings for HaXe/Neko

Lee Sylvester
You can use val_gc. This gives you the ability to assign a function to
your abstract value that gets called when the garbage collector makes
its rounds. Essentially, you might do something like :

void dispose( value v )
{
    free_data( val_data(v)->customValue );
    free_data( val_data(v) );
}
 
value createWidget()
{
    value v = alloc_abstract( k_myWidget, new MyWidget() );
    val_gc( v, dispose );
    return v;
}


That should do it.

Best,
Lee




Simon TRENY wrote:

> Ok, thanks! :)
>
> Now, how can I know when an object is destroyed by the
> garbage-collector? I would need to know that in order to call the
> "dispose" function to free the custom-value, right?
>
> Simon
>
>
> On Tue, 11 Nov 2008 19:43:56 +0000,
> Lee McColl Sylvester <[hidden email]> wrote :
>
>  
>> Ahh, I see what you're saying. You've got it reversed. What would
>> normally happen is you'd dispose of your widget, then in the widgets
>> destructor, you'd do something like :
>>
>> void* ~ButtonWidget()
>> {
>>     alloc_free( customValue );
>> }
>>
>> Or, if you're calling it externally,
>>
>> value dispose( value widget )
>> {
>>     alloc_free( val_data( widget )->customValue );
>> }
>>
>> Then, you just make sure you call this before disposing of your
>> object in haXe.
>>
>> Lee
>>
>>
>>
>>
>>
>> Simon TRENY wrote:
>>    
>>> Thanks for the explanation! :)
>>>
>>> Actually, I have already used the same system to add an
>>> "onTouchDown" and an "onTouchUp" callback to the widget, so the
>>> user can do special action when a widget is clicked, and it works
>>> indeed pretty well.
>>>
>>> But the thing I don't understand is, if I use alloc_root(1) and I
>>> store the abstract-value in it, the abstract value will always be
>>> referenced (since it's will appear as a root-value for the GC), so
>>> it will never be garbage-collected and I won't be able to know when
>>> the widget-object is destroyed. Or maybe I'm missing something?
>>>
>>> Regards,
>>> Simon
>>>
>>>
>>> On Tue, 11 Nov 2008 18:34:37 +0000,
>>> Lee McColl Sylvester <[hidden email]> wrote :
>>>
>>>  
>>>      
>>>> I guess this needs elaboration... Okay..
>>>>
>>>> Imagine I have a widget, and that widget can call a custom method
>>>> with the signature
>>>>
>>>> void* myButtonCallback( myEvent* event );
>>>>
>>>> Now, the problem is, I can't create a method like that in haXe,
>>>> because all my methods accept type value and return type value...
>>>> Even null is of type value. Ergo, what I do is create a standard
>>>> method to handle all my widget events, but have that method call a
>>>> custom function for that widget. Ergo:
>>>>
>>>> void* myButtonCallback( myEvent* event )
>>>> {
>>>>     value func = (value) *myEvent->customHaXeFunctionValue;
>>>>     val_call1( func, alloc_int( myEvent->buttonId ) );
>>>> }
>>>>
>>>> Now, when creating my widget, I simply provide a method that will
>>>> allow people to assign a handler method to that widget, but use
>>>> alloc_root() to handle the reservation of memory
>>>>
>>>> value addWidgetClickHandler( value widget, value handler )
>>>> {
>>>>     value* func;
>>>>     val_check( widget, kind_buttonwidget );
>>>>     val_check_function( handler, 0 );
>>>>     func = alloc_root( 1 );
>>>>     *func = handler;
>>>>     ButtonWidget buttwedge = val_data( widget );
>>>>     buttwedge.custom = func;
>>>> }
>>>>
>>>> There. That should do it, though I've not tested it, so there may
>>>> be typos ;-)  I've done this loads, myself, and it works a treat.
>>>> The good thing is, you get to assign a custom function to each
>>>> widget without breaking your old code, and without providing any
>>>> *magic* ;-)
>>>>
>>>> Lee
>>>>
>>>>
>>>>
>>>>
>>>> Lee McColl Sylvester wrote:
>>>>    
>>>>        
>>>>> You don't use the alloc_root on the widget, you use it on the
>>>>> item you'd add to void*. This way, the memory is reserved and
>>>>> won't be overwritten. The widget gets handled (partially) through
>>>>> alloc_abstract, though you still need to be careful of how your
>>>>> memory is being cleaned / reused. I'm guessing you've already
>>>>> thought about that in your library, though ;-)
>>>>>
>>>>> Lee
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> Simon TRENY wrote:
>>>>>      
>>>>>          
>>>>>> On Tue, 11 Nov 2008 18:24:39 +0100,
>>>>>> Nicolas Cannasse <[hidden email]> wrote :
>>>>>>
>>>>>>  
>>>>>>        
>>>>>>            
>>>>>>> Simon TRENY a écrit :
>>>>>>>    
>>>>>>>          
>>>>>>>              
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>>
>>>>>>>> I'm having a problem with creating haXe bindings for an
>>>>>>>> existing library I have written in C. Here is a simple
>>>>>>>> function of the API I'd like to bind:
>>>>>>>> Widget *widget_parent_get(Widget *widget); //Get the widget's
>>>>>>>> parent
>>>>>>>>            
>>>>>>>>                
>>>>>>> [...]
>>>>>>>    
>>>>>>>          
>>>>>>>              
>>>>>>>> Is there a better way to bind this function that solves these
>>>>>>>> problems?
>>>>>>>>      
>>>>>>>>            
>>>>>>>>                
>>>>>>> Yes, that's a common problem when adding two levels of
>>>>>>> abstraction. First, I hope that you can bind a void* to your
>>>>>>> Widget (as a "custom" value). In that case, use an alloc_root(1)
>>>>>>> and for each widget, store the corresponding abstract value. In
>>>>>>> case the Widget get destroyed,
>>>>>>> you can use free_root + set the abstract kind to NULL, which
>>>>>>> will prevent any further api calls on this widget.
>>>>>>>    
>>>>>>>          
>>>>>>>              
>>>>>> Ok, thanks, adding a void * to the structure won't be a problem.
>>>>>> But there is one thing I don't understand with this solution: if
>>>>>> I call alloc_root() on the abstract, won't it prevent the widget
>>>>>> to be garbage-collected? For now, i use a finalizer on the
>>>>>> abstract, and in the finalizer, I destroy the associated widget.
>>>>>> This way, I can destroy the widget when it is no longer
>>>>>> referenced. Would this still work with this solution?
>>>>>>
>>>>>>  
>>>>>>        
>>>>>>            
>>>>>>> Now that you have a strong abstract <-> widget binding,
>>>>>>> allocating an object everytime is not a big problem, except for
>>>>>>> ==. In that case - and only for neko - you can define the
>>>>>>> __compare method that will compare two objects abstracts.
>>>>>>>
>>>>>>> For instance :
>>>>>>>
>>>>>>> private function __compare( w : Widget ) {
>>>>>>>     return untyped __dollar__compare( abstract, w.abstract );
>>>>>>> }
>>>>>>>    
>>>>>>>          
>>>>>>>              
>>>>>> Ok, that will work great, neko is the only target! :)
>>>>>>
>>>>>> But, to avoid the allocating the object each time, wouldn't it be
>>>>>> possible to use a hash-table indexed by the abstract? It would
>>>>>> require the abstract to be hashable and comparable though. I
>>>>>> don't know if it's possible? And what would be more efficient:
>>>>>> allocating each time, or using the hash-table approach?
>>>>>>
>>>>>>
>>>>>> Thanks for your help :)
>>>>>> Simon
>>>>>>
>>>>>>  
>>>>>>        
>>>>>>            
>>>>>      
>>>>>          
>>>>    
>>>>        
>>>  
>>>      
>>    
>
>  


--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Problem creating bindings for HaXe/Neko

Simon TRENY
Sorry to annoy you again, but there is definitely something I don't
understand. If I take your code and add the alloc_root() thing we
discussed before, it will look something like this:

void dispose(value v)
{
    MyWidget *wid = val_data(v);

    free_root(wid->customValue);
    delete wid;
}
 
value createWidget()
{
    MyWidget *wid = new MyWidget();
    value v = alloc_abstract(k_myWidget, wid);
    val_gc(v, dispose);
   
    wid->customValue = alloc_root(1);
    *wid->customValue = v;

    return v;
}

If I do that, the abstract-value will be a root-value of the GC and
thus will never be collected. And so, dispose() will never get called
neither. Sorry to bother you with that but I really don't see how
this works! :)

Thanks for your help Lee!
Simon


On Tue, 11 Nov 2008 20:04:17 +0000,
Lee McColl Sylvester <[hidden email]> wrote :

> You can use val_gc. This gives you the ability to assign a function
> to your abstract value that gets called when the garbage collector
> makes its rounds. Essentially, you might do something like :
>
> void dispose( value v )
> {
>     free_data( val_data(v)->customValue );
>     free_data( val_data(v) );
> }
>  
> value createWidget()
> {
>     value v = alloc_abstract( k_myWidget, new MyWidget() );
>     val_gc( v, dispose );
>     return v;
> }
>
>
> That should do it.
>
> Best,
> Lee
>
>
>
>
> Simon TRENY wrote:
> > Ok, thanks! :)
> >
> > Now, how can I know when an object is destroyed by the
> > garbage-collector? I would need to know that in order to call the
> > "dispose" function to free the custom-value, right?
> >
> > Simon
> >
> >
> > On Tue, 11 Nov 2008 19:43:56 +0000,
> > Lee McColl Sylvester <[hidden email]> wrote :
> >
> >  
> >> Ahh, I see what you're saying. You've got it reversed. What would
> >> normally happen is you'd dispose of your widget, then in the
> >> widgets destructor, you'd do something like :
> >>
> >> void* ~ButtonWidget()
> >> {
> >>     alloc_free( customValue );
> >> }
> >>
> >> Or, if you're calling it externally,
> >>
> >> value dispose( value widget )
> >> {
> >>     alloc_free( val_data( widget )->customValue );
> >> }
> >>
> >> Then, you just make sure you call this before disposing of your
> >> object in haXe.
> >>
> >> Lee
> >>
> >>
> >>
> >>
> >>
> >> Simon TRENY wrote:
> >>    
> >>> Thanks for the explanation! :)
> >>>
> >>> Actually, I have already used the same system to add an
> >>> "onTouchDown" and an "onTouchUp" callback to the widget, so the
> >>> user can do special action when a widget is clicked, and it works
> >>> indeed pretty well.
> >>>
> >>> But the thing I don't understand is, if I use alloc_root(1) and I
> >>> store the abstract-value in it, the abstract value will always be
> >>> referenced (since it's will appear as a root-value for the GC), so
> >>> it will never be garbage-collected and I won't be able to know
> >>> when the widget-object is destroyed. Or maybe I'm missing
> >>> something?
> >>>
> >>> Regards,
> >>> Simon
> >>>
> >>>
> >>> On Tue, 11 Nov 2008 18:34:37 +0000,
> >>> Lee McColl Sylvester <[hidden email]> wrote :
> >>>
> >>>  
> >>>      
> >>>> I guess this needs elaboration... Okay..
> >>>>
> >>>> Imagine I have a widget, and that widget can call a custom method
> >>>> with the signature
> >>>>
> >>>> void* myButtonCallback( myEvent* event );
> >>>>
> >>>> Now, the problem is, I can't create a method like that in haXe,
> >>>> because all my methods accept type value and return type value...
> >>>> Even null is of type value. Ergo, what I do is create a standard
> >>>> method to handle all my widget events, but have that method call
> >>>> a custom function for that widget. Ergo:
> >>>>
> >>>> void* myButtonCallback( myEvent* event )
> >>>> {
> >>>>     value func = (value) *myEvent->customHaXeFunctionValue;
> >>>>     val_call1( func, alloc_int( myEvent->buttonId ) );
> >>>> }
> >>>>
> >>>> Now, when creating my widget, I simply provide a method that will
> >>>> allow people to assign a handler method to that widget, but use
> >>>> alloc_root() to handle the reservation of memory
> >>>>
> >>>> value addWidgetClickHandler( value widget, value handler )
> >>>> {
> >>>>     value* func;
> >>>>     val_check( widget, kind_buttonwidget );
> >>>>     val_check_function( handler, 0 );
> >>>>     func = alloc_root( 1 );
> >>>>     *func = handler;
> >>>>     ButtonWidget buttwedge = val_data( widget );
> >>>>     buttwedge.custom = func;
> >>>> }
> >>>>
> >>>> There. That should do it, though I've not tested it, so there may
> >>>> be typos ;-)  I've done this loads, myself, and it works a treat.
> >>>> The good thing is, you get to assign a custom function to each
> >>>> widget without breaking your old code, and without providing any
> >>>> *magic* ;-)
> >>>>
> >>>> Lee
> >>>>
> >>>>
> >>>>
> >>>>
> >>>> Lee McColl Sylvester wrote:
> >>>>    
> >>>>        
> >>>>> You don't use the alloc_root on the widget, you use it on the
> >>>>> item you'd add to void*. This way, the memory is reserved and
> >>>>> won't be overwritten. The widget gets handled (partially)
> >>>>> through alloc_abstract, though you still need to be careful of
> >>>>> how your memory is being cleaned / reused. I'm guessing you've
> >>>>> already thought about that in your library, though ;-)
> >>>>>
> >>>>> Lee
> >>>>>
> >>>>>
> >>>>>
> >>>>>
> >>>>> Simon TRENY wrote:
> >>>>>      
> >>>>>          
> >>>>>> On Tue, 11 Nov 2008 18:24:39 +0100,
> >>>>>> Nicolas Cannasse <[hidden email]> wrote :
> >>>>>>
> >>>>>>  
> >>>>>>        
> >>>>>>            
> >>>>>>> Simon TRENY a écrit :
> >>>>>>>    
> >>>>>>>          
> >>>>>>>              
> >>>>>>>> Hi,
> >>>>>>>>
> >>>>>>>>
> >>>>>>>> I'm having a problem with creating haXe bindings for an
> >>>>>>>> existing library I have written in C. Here is a simple
> >>>>>>>> function of the API I'd like to bind:
> >>>>>>>> Widget *widget_parent_get(Widget *widget); //Get the widget's
> >>>>>>>> parent
> >>>>>>>>            
> >>>>>>>>                
> >>>>>>> [...]
> >>>>>>>    
> >>>>>>>          
> >>>>>>>              
> >>>>>>>> Is there a better way to bind this function that solves these
> >>>>>>>> problems?
> >>>>>>>>      
> >>>>>>>>            
> >>>>>>>>                
> >>>>>>> Yes, that's a common problem when adding two levels of
> >>>>>>> abstraction. First, I hope that you can bind a void* to your
> >>>>>>> Widget (as a "custom" value). In that case, use an
> >>>>>>> alloc_root(1) and for each widget, store the corresponding
> >>>>>>> abstract value. In case the Widget get destroyed,
> >>>>>>> you can use free_root + set the abstract kind to NULL, which
> >>>>>>> will prevent any further api calls on this widget.
> >>>>>>>    
> >>>>>>>          
> >>>>>>>              
> >>>>>> Ok, thanks, adding a void * to the structure won't be a
> >>>>>> problem. But there is one thing I don't understand with this
> >>>>>> solution: if I call alloc_root() on the abstract, won't it
> >>>>>> prevent the widget to be garbage-collected? For now, i use a
> >>>>>> finalizer on the abstract, and in the finalizer, I destroy the
> >>>>>> associated widget. This way, I can destroy the widget when it
> >>>>>> is no longer referenced. Would this still work with this
> >>>>>> solution?
> >>>>>>
> >>>>>>  
> >>>>>>        
> >>>>>>            
> >>>>>>> Now that you have a strong abstract <-> widget binding,
> >>>>>>> allocating an object everytime is not a big problem, except
> >>>>>>> for ==. In that case - and only for neko - you can define the
> >>>>>>> __compare method that will compare two objects abstracts.
> >>>>>>>
> >>>>>>> For instance :
> >>>>>>>
> >>>>>>> private function __compare( w : Widget ) {
> >>>>>>>     return untyped __dollar__compare( abstract, w.abstract );
> >>>>>>> }
> >>>>>>>    
> >>>>>>>          
> >>>>>>>              
> >>>>>> Ok, that will work great, neko is the only target! :)
> >>>>>>
> >>>>>> But, to avoid the allocating the object each time, wouldn't it
> >>>>>> be possible to use a hash-table indexed by the abstract? It
> >>>>>> would require the abstract to be hashable and comparable
> >>>>>> though. I don't know if it's possible? And what would be more
> >>>>>> efficient: allocating each time, or using the hash-table
> >>>>>> approach?
> >>>>>>
> >>>>>>
> >>>>>> Thanks for your help :)
> >>>>>> Simon
> >>>>>>
> >>>>>>  
> >>>>>>        
> >>>>>>            
> >>>>>      
> >>>>>          
> >>>>    
> >>>>        
> >>>  
> >>>      
> >>    
> >
> >  
>
>

--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Problem creating bindings for HaXe/Neko

Lee Sylvester
What you've done makes no sense ;-)  You've wrapped the widget into a
value object, then assigned it to itself. Hehe

I thought you wanted to add a function callback as a custom value?   In
which case, it might look like :

void widgetClick( MyWidget *self )
{
    val_call1( *(MyWidget*)val_data( wid )->customValue, self->id );
}
 
void dispose(value v)
{
    MyWidget *wid = val_data(v);

    free_root(wid->customValue);
    delete wid;
}
 
value createWidget()
{
    MyWidget *wid = new MyWidget();
    wid->clickHandler = &widgetClick;
    value v = alloc_abstract(k_myWidget, wid);
    val_gc(v, dispose);

    return v;
}

value addClickHandler( value wid, value handler )
{
    val_check_function( handler, 1 );
    (MyWidget*)val_data( wid )->customValue = alloc_root(1);
    *(MyWidget*)val_data( wid )->customValue = handler;
}


Hope that helps ;-)

Lee





Simon TRENY wrote:

> Sorry to annoy you again, but there is definitely something I don't
> understand. If I take your code and add the alloc_root() thing we
> discussed before, it will look something like this:
>
> void dispose(value v)
> {
>     MyWidget *wid = val_data(v);
>
>     free_root(wid->customValue);
>     delete wid;
> }
>  
> value createWidget()
> {
>     MyWidget *wid = new MyWidget();
>     value v = alloc_abstract(k_myWidget, wid);
>     val_gc(v, dispose);
>    
>     wid->customValue = alloc_root(1);
>     *wid->customValue = v;
>
>     return v;
> }
>
> If I do that, the abstract-value will be a root-value of the GC and
> thus will never be collected. And so, dispose() will never get called
> neither. Sorry to bother you with that but I really don't see how
> this works! :)
>
> Thanks for your help Lee!
> Simon
>
>
> On Tue, 11 Nov 2008 20:04:17 +0000,
> Lee McColl Sylvester <[hidden email]> wrote :
>
>  
>> You can use val_gc. This gives you the ability to assign a function
>> to your abstract value that gets called when the garbage collector
>> makes its rounds. Essentially, you might do something like :
>>
>> void dispose( value v )
>> {
>>     free_data( val_data(v)->customValue );
>>     free_data( val_data(v) );
>> }
>>  
>> value createWidget()
>> {
>>     value v = alloc_abstract( k_myWidget, new MyWidget() );
>>     val_gc( v, dispose );
>>     return v;
>> }
>>
>>
>> That should do it.
>>
>> Best,
>> Lee
>>
>>
>>
>>
>> Simon TRENY wrote:
>>    
>>> Ok, thanks! :)
>>>
>>> Now, how can I know when an object is destroyed by the
>>> garbage-collector? I would need to know that in order to call the
>>> "dispose" function to free the custom-value, right?
>>>
>>> Simon
>>>
>>>
>>> On Tue, 11 Nov 2008 19:43:56 +0000,
>>> Lee McColl Sylvester <[hidden email]> wrote :
>>>
>>>  
>>>      
>>>> Ahh, I see what you're saying. You've got it reversed. What would
>>>> normally happen is you'd dispose of your widget, then in the
>>>> widgets destructor, you'd do something like :
>>>>
>>>> void* ~ButtonWidget()
>>>> {
>>>>     alloc_free( customValue );
>>>> }
>>>>
>>>> Or, if you're calling it externally,
>>>>
>>>> value dispose( value widget )
>>>> {
>>>>     alloc_free( val_data( widget )->customValue );
>>>> }
>>>>
>>>> Then, you just make sure you call this before disposing of your
>>>> object in haXe.
>>>>
>>>> Lee
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> Simon TRENY wrote:
>>>>    
>>>>        
>>>>> Thanks for the explanation! :)
>>>>>
>>>>> Actually, I have already used the same system to add an
>>>>> "onTouchDown" and an "onTouchUp" callback to the widget, so the
>>>>> user can do special action when a widget is clicked, and it works
>>>>> indeed pretty well.
>>>>>
>>>>> But the thing I don't understand is, if I use alloc_root(1) and I
>>>>> store the abstract-value in it, the abstract value will always be
>>>>> referenced (since it's will appear as a root-value for the GC), so
>>>>> it will never be garbage-collected and I won't be able to know
>>>>> when the widget-object is destroyed. Or maybe I'm missing
>>>>> something?
>>>>>
>>>>> Regards,
>>>>> Simon
>>>>>
>>>>>
>>>>> On Tue, 11 Nov 2008 18:34:37 +0000,
>>>>> Lee McColl Sylvester <[hidden email]> wrote :
>>>>>
>>>>>  
>>>>>      
>>>>>          
>>>>>> I guess this needs elaboration... Okay..
>>>>>>
>>>>>> Imagine I have a widget, and that widget can call a custom method
>>>>>> with the signature
>>>>>>
>>>>>> void* myButtonCallback( myEvent* event );
>>>>>>
>>>>>> Now, the problem is, I can't create a method like that in haXe,
>>>>>> because all my methods accept type value and return type value...
>>>>>> Even null is of type value. Ergo, what I do is create a standard
>>>>>> method to handle all my widget events, but have that method call
>>>>>> a custom function for that widget. Ergo:
>>>>>>
>>>>>> void* myButtonCallback( myEvent* event )
>>>>>> {
>>>>>>     value func = (value) *myEvent->customHaXeFunctionValue;
>>>>>>     val_call1( func, alloc_int( myEvent->buttonId ) );
>>>>>> }
>>>>>>
>>>>>> Now, when creating my widget, I simply provide a method that will
>>>>>> allow people to assign a handler method to that widget, but use
>>>>>> alloc_root() to handle the reservation of memory
>>>>>>
>>>>>> value addWidgetClickHandler( value widget, value handler )
>>>>>> {
>>>>>>     value* func;
>>>>>>     val_check( widget, kind_buttonwidget );
>>>>>>     val_check_function( handler, 0 );
>>>>>>     func = alloc_root( 1 );
>>>>>>     *func = handler;
>>>>>>     ButtonWidget buttwedge = val_data( widget );
>>>>>>     buttwedge.custom = func;
>>>>>> }
>>>>>>
>>>>>> There. That should do it, though I've not tested it, so there may
>>>>>> be typos ;-)  I've done this loads, myself, and it works a treat.
>>>>>> The good thing is, you get to assign a custom function to each
>>>>>> widget without breaking your old code, and without providing any
>>>>>> *magic* ;-)
>>>>>>
>>>>>> Lee
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> Lee McColl Sylvester wrote:
>>>>>>    
>>>>>>        
>>>>>>            
>>>>>>> You don't use the alloc_root on the widget, you use it on the
>>>>>>> item you'd add to void*. This way, the memory is reserved and
>>>>>>> won't be overwritten. The widget gets handled (partially)
>>>>>>> through alloc_abstract, though you still need to be careful of
>>>>>>> how your memory is being cleaned / reused. I'm guessing you've
>>>>>>> already thought about that in your library, though ;-)
>>>>>>>
>>>>>>> Lee
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> Simon TRENY wrote:
>>>>>>>      
>>>>>>>          
>>>>>>>              
>>>>>>>> On Tue, 11 Nov 2008 18:24:39 +0100,
>>>>>>>> Nicolas Cannasse <[hidden email]> wrote :
>>>>>>>>
>>>>>>>>  
>>>>>>>>        
>>>>>>>>            
>>>>>>>>                
>>>>>>>>> Simon TRENY a écrit :
>>>>>>>>>    
>>>>>>>>>          
>>>>>>>>>              
>>>>>>>>>                  
>>>>>>>>>> Hi,
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> I'm having a problem with creating haXe bindings for an
>>>>>>>>>> existing library I have written in C. Here is a simple
>>>>>>>>>> function of the API I'd like to bind:
>>>>>>>>>> Widget *widget_parent_get(Widget *widget); //Get the widget's
>>>>>>>>>> parent
>>>>>>>>>>            
>>>>>>>>>>                
>>>>>>>>>>                    
>>>>>>>>> [...]
>>>>>>>>>    
>>>>>>>>>          
>>>>>>>>>              
>>>>>>>>>                  
>>>>>>>>>> Is there a better way to bind this function that solves these
>>>>>>>>>> problems?
>>>>>>>>>>      
>>>>>>>>>>            
>>>>>>>>>>                
>>>>>>>>>>                    
>>>>>>>>> Yes, that's a common problem when adding two levels of
>>>>>>>>> abstraction. First, I hope that you can bind a void* to your
>>>>>>>>> Widget (as a "custom" value). In that case, use an
>>>>>>>>> alloc_root(1) and for each widget, store the corresponding
>>>>>>>>> abstract value. In case the Widget get destroyed,
>>>>>>>>> you can use free_root + set the abstract kind to NULL, which
>>>>>>>>> will prevent any further api calls on this widget.
>>>>>>>>>    
>>>>>>>>>          
>>>>>>>>>              
>>>>>>>>>                  
>>>>>>>> Ok, thanks, adding a void * to the structure won't be a
>>>>>>>> problem. But there is one thing I don't understand with this
>>>>>>>> solution: if I call alloc_root() on the abstract, won't it
>>>>>>>> prevent the widget to be garbage-collected? For now, i use a
>>>>>>>> finalizer on the abstract, and in the finalizer, I destroy the
>>>>>>>> associated widget. This way, I can destroy the widget when it
>>>>>>>> is no longer referenced. Would this still work with this
>>>>>>>> solution?
>>>>>>>>
>>>>>>>>  
>>>>>>>>        
>>>>>>>>            
>>>>>>>>                
>>>>>>>>> Now that you have a strong abstract <-> widget binding,
>>>>>>>>> allocating an object everytime is not a big problem, except
>>>>>>>>> for ==. In that case - and only for neko - you can define the
>>>>>>>>> __compare method that will compare two objects abstracts.
>>>>>>>>>
>>>>>>>>> For instance :
>>>>>>>>>
>>>>>>>>> private function __compare( w : Widget ) {
>>>>>>>>>     return untyped __dollar__compare( abstract, w.abstract );
>>>>>>>>> }
>>>>>>>>>    
>>>>>>>>>          
>>>>>>>>>              
>>>>>>>>>                  
>>>>>>>> Ok, that will work great, neko is the only target! :)
>>>>>>>>
>>>>>>>> But, to avoid the allocating the object each time, wouldn't it
>>>>>>>> be possible to use a hash-table indexed by the abstract? It
>>>>>>>> would require the abstract to be hashable and comparable
>>>>>>>> though. I don't know if it's possible? And what would be more
>>>>>>>> efficient: allocating each time, or using the hash-table
>>>>>>>> approach?
>>>>>>>>
>>>>>>>>
>>>>>>>> Thanks for your help :)
>>>>>>>> Simon
>>>>>>>>
>>>>>>>>  
>>>>>>>>        
>>>>>>>>            
>>>>>>>>                
>>>>>>>      
>>>>>>>          
>>>>>>>              
>>>>>>    
>>>>>>        
>>>>>>            
>>>>>  
>>>>>      
>>>>>          
>>>>    
>>>>        
>>>  
>>>      
>>    
>
>  


--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Problem creating bindings for HaXe/Neko

Gamehaxe
In reply to this post by Simon TRENY
One thing, especially with external widget libraries such as
wxWindows, it to be quite sure about who owns the window.

eg:

var frame = new gui.Frame();
var button = new gui.Button(frame);

button = 0; // or event the button variable goes out of scope

Setting button = 0 frees the last reference to the button,
making it possible for GC to reclaim it.  If you have registered
a finalizer on it, then that will be called eventually
(note: not right away).  The GC does not know that the frame
has an internal pointer to the child button, unless you
somehow tell it.

This it probably not what you want, since the frame still
probably wants the button.  Were you trying to delete the button?

So one way would be to *explicitly* destroy the windows,
ie do not use garbage collection for your external widgets.
I reallity, you would probably only worry about the top
level frames/ dialogs, since the will delete their children
automatically.  This would be something like "frame.destroy()"
which would call "delete real_frame_pointer" in your lib.
(Or "frame->Destroy()" on wxWindows I think).

As for the window holding a reference to the callback function,
this can be done in the destructor of the widget using
the "alloc_root" methods already discussed.
Or you have member pointers in you class, you could register
your whole class with GC and release it in your destructor,
thereby ensuring the member pointers are "held open" for
the GC.

You can store the window pointers in neko, but it does not own them.

Hugh

--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Problem creating bindings for HaXe/Neko

Simon TRENY
On Wed, 12 Nov 2008 19:21:16 +0900,
"Hugh Sanderson" <[hidden email]> wrote :

> One thing, especially with external widget libraries such as
> wxWindows, it to be quite sure about who owns the window.
>
> eg:
>
> var frame = new gui.Frame();
> var button = new gui.Button(frame);
>
> button = 0; // or event the button variable goes out of scope
>
> Setting button = 0 frees the last reference to the button,
> making it possible for GC to reclaim it.  If you have registered
> a finalizer on it, then that will be called eventually
> (note: not right away).  The GC does not know that the frame
> has an internal pointer to the child button, unless you
> somehow tell it.
>
> This it probably not what you want, since the frame still
> probably wants the button.  Were you trying to delete the button?

You're right, that definitely can be a problem. One way to fix this,
and still taking profit of garbage-collection, could be to use
manual reference-counting: when you create your button, it has a
reference-counter set to 1 (which is the reference held by the
abstract value). In the finalizer of the abstract value, you
unreference the button (i.e. decrease its reference-counter). If its
reference-counter is set to 0, you can safely destroy it. Otherwise, it
means that another widget (here, the frame) still references the button.
The problem with this method is that the toolkit has to support
reference-counting (Gtk does, I don't about wxWidget).

Simon

>
> So one way would be to *explicitly* destroy the windows,
> ie do not use garbage collection for your external widgets.
> I reallity, you would probably only worry about the top
> level frames/ dialogs, since the will delete their children
> automatically.  This would be something like "frame.destroy()"
> which would call "delete real_frame_pointer" in your lib.
> (Or "frame->Destroy()" on wxWindows I think).
>
> As for the window holding a reference to the callback function,
> this can be done in the destructor of the widget using
> the "alloc_root" methods already discussed.
> Or you have member pointers in you class, you could register
> your whole class with GC and release it in your destructor,
> thereby ensuring the member pointers are "held open" for
> the GC.
>
> You can store the window pointers in neko, but it does not own them.
>
> Hugh
>

--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Problem creating bindings for HaXe/Neko

Gamehaxe
... One way to fix this,
> and still taking profit of garbage-collection, could be to use
> manual reference-counting: when you create your button, it has a
> reference-counter set to 1 (which is the reference held by the
> abstract value). In the finalizer of the abstract value, you
> unreference the button (i.e. decrease its reference-counter). If its
> reference-counter is set to 0, you can safely destroy it.

Yes, but that could be tricky with the implicit parent/child relation
- these would need to correctly ref-count.

In neash, the "DrawObjects" are stored in a list haxe side.
These are garbage collected via the "abstract" interface.
However, these have resources, such as bitmaps, which are
reference counted.  So you can combine ref-counting and garbage
collection, but I'm not sure about doing it on every widget.

You could potentailly do it on every top-level window (eg "frame").
Or perhaps "Form" would be a better example. I think some
concrete use cases would help. Maybe something like this:

function GetConfirm()
{
    var message_box = new gui.MessageBox("Delete file?",["Yes","No"]);
    return message_box->run()=="Yes";
}

Here it would be good the have message_box auto-delete, and I
think "ownership" of the top level window (form) is pretty clear.
But even this get tricky if you get something like this:

function GetConfirm()
{
    var message_box = new gui.MessageBox("Delete file?",["Yes","No"]);
    // store something for later ....
    class_member_variable = message_box.findButton("Yes");
    return message_box->run()=="Yes";
}


What about something that you just want to fire-off and
handle via callbacks.  eg:

function CreateColourPalette()
{
    var palette = new gui.ColourPalette();
    palette->onApply = SetColour;
    // palette is now just floating, with no references
}

Here you want it floating until the user hits the close button.

Maybe you need a flag to say if it's a control is GC?
But I can't really see how this would work with child control references.

Finally, you could use the Boehm GC-trick of replacing the "new" function
with a GC-version. I expect this would have big problems with
existing widget sets because of the non-deterministic destructors.

Hugh




--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Problem creating bindings for HaXe/Neko

Simon TRENY
In reply to this post by Simon TRENY
On Tue, 11 Nov 2008 19:11:12 +0100,
Simon TRENY <[hidden email]> wrote :

> On Tue, 11 Nov 2008 18:24:39 +0100,
> Nicolas Cannasse <[hidden email]> wrote :
>
> > Simon TRENY a écrit :
> > > Hi,
> > >
> > >
> > > I'm having a problem with creating haXe bindings for an existing
> > > library I have written in C. Here is a simple function of the API
> > > I'd like to bind:
> > > Widget *widget_parent_get(Widget *widget); //Get the widget's
> > > parent
> > [...]
> > > Is there a better way to bind this function that solves these
> > > problems?
> >
> > Yes, that's a common problem when adding two levels of abstraction.
> > First, I hope that you can bind a void* to your Widget (as a
> > "custom" value). In that case, use an alloc_root(1) and for each
> > widget, store the corresponding abstract value. In case the Widget
> > get destroyed, you can use free_root + set the abstract kind to
> > NULL, which will prevent any further api calls on this widget.
> Ok, thanks, adding a void * to the structure won't be a problem.
> But there is one thing I don't understand with this solution: if I
> call alloc_root() on the abstract, won't it prevent the widget to be
> garbage-collected? For now, i use a finalizer on the abstract, and in
> the finalizer, I destroy the associated widget. This way, I can
> destroy the widget when it is no longer referenced. Would this still
> work with this solution?
>
> >
> > Now that you have a strong abstract <-> widget binding, allocating
> > an object everytime is not a big problem, except for ==. In that
> > case - and only for neko - you can define the __compare method that
> > will compare two objects abstracts.
> >
> > For instance :
> >
> > private function __compare( w : Widget ) {
> > return untyped __dollar__compare( abstract, w.abstract );
> > }
> Ok, that will work great, neko is the only target! :)
>
> But, to avoid the allocating the object each time, wouldn't it be
> possible to use a hash-table indexed by the abstract? It would require
> the abstract to be hashable and comparable though. I don't know if
> it's possible? And what would be more efficient: allocating each time,
> or using the hash-table approach?

Nicolas, would it be possible to associate an Haxe object to an abstract
value and to retrieve it later? It could help a lot when writing
bindings for Haxe, since we won't have to create a new object each time
we call a method such as Widget.getParent() for example (it will be
created just the first time).

For example, for the getParent() method, we could have:

class Widget
{
   var handle : Abstract;
   
   public function getParent() : Widget
   {
      var parentHandle = get_parent(this.handle);
      var parent = neko.Lib.getAssociatedObject(parentHandle);

      if (parent == null)
      {
         parent = new Widget(parentHandle);
         neko.Lib.setAssociatedObject(parentHandle, parent);
      }
     
      return parent;
   }

   static var get_parent = neko.Lib.load("", "get_parent", 1);
}


Regards,
Simon

>
>
> Thanks for your help :)
> Simon
>

--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Problem creating bindings for HaXe/Neko

Nicolas Cannasse
Simon TRENY a écrit :
> Nicolas, would it be possible to associate an Haxe object to an abstract
> value and to retrieve it later? It could help a lot when writing

You can store it in your abstract data :

typedef struct adata {
        value object;
        Widget *widget;
};

(don't forget to use neko alloc() for allocating this memory).

You'll have then to add calls to getObject/setObject for your abstract,
do haXe can deal with it.

OTOH, checking if an object is associated might be a bit useless. An
haxe Object with one instance field only takes 3 blocks for a total of
28 bytes of memory.

Nicolas

--
haXe - an open source web programming language
http://haxe.org