|
From: Charlie S. <cf...@in...> - 2006-03-07 18:44:03
|
FYI - wrapping this as a constructor doesn't actually work either.
Trying to do a solution just on the point class:
%rename("marshal_load") Point::Point(std::string);
%extend Point {
/* Add in marshalling support */
Point(std::string data)
{
}
}
Interestingly enough, this will generate an allocate method (not sure
why, but it doesn't hurt):
_wrap_marshal_load_allocate(VALUE self) {
...
}
And here is correct wrapper code:
_wrap_new_marshal_load(int argc, VALUE *argv, VALUE self) {
..
result = (geos::Point *)new_geos_Point(arg1);DATA_PTR(self) = result;
return self;
}
But the following line should exist but does not:
rb_define_method(cPoint.klass, "marshal_load",
VALUEFUNC(_wrap_new_marshal_load), -1);
Seems like renaming constructors doesn't work - I'd guess this is a bug?
Taking a different approach - is there any way to use %init {} to put
code at the end of the initialization block, and not the start? If so,
then I could add this method in myself manually for now.
Anyway, seems like I'm stuck.
Charlie
Marcelo Matus wrote:
> Sorry, I forgot %newobject
>
> %newobject Geometry::from_s;
> %factory(geos::Geometry::from_s,....);
>
> namespace geos {
> %extend Geometry {
> static Geometry *from_s(const std::string& s) { ... }
> }
>
> this is exacty as the 'create' case in li_factory.i, and that works fine.
>
> Ans %newobject tells swig to treat Geometry::from_s as a constructor,
> or alike,
> since it tells swig the object was just created.
>
> Marcelo
>
> Charlie Savage wrote:
>
>> Unfortunately this doesn't work. The from_s method creates a new
>> Geometry and returns it back to Ruby. Remember that Ruby has a a 2
>> stage object creation:
>>
>> 1. Allocate an object
>> 2. Initialize an object
>>
>> When unmarshaling data Ruby calls a method on an object instance
>> called marshal_load. This method is called instead of the intialize
>> method (step #2 above). Which means it occurs in an instance of a
>> Ruby object and therefore must update that Ruby object, not return a
>> new one (which is what the static method does). Thus, its works just
>> like a constructor and should be wrapped just like one.
>>
>> So just to review the options. You can't fake it as a regular method
>> because in the generated code SWIG will try to extract out the C++
>> object from the Ruby object via SWIG_ConvertPtr. But there is no C++
>> object yet!
>>
> well, the same as 'create', ie
>
> static Geometry *from_s(const std::string& s) { <do
> unmarhalling>; return ptr; }
>
> here SWIG_ConvertPtr will be applied after the objet is created and
> returned via 'return ptr'.
>
>
>> And you can't fake it as a static method because that gets mapped to
>> a class method in Ruby - but marshal_load has to be an instance
>> method. So the Ruby VM is not happy.
>>
> even for static methods?, static methods shouldn't need an instance,
> right?
>
> How does the li_factory.i test work then with ruby?
>
>
>> It can be constructor (defined using %extend) but there are few major
>> downsides. First, it could interfere with a pre-existing
>> constructors that takes a string. Second, Ruby actually has two
>> marshaling systems so you'd have a hard-time supporting both. Third,
>> using a constructor doesn't work in cases like this one where the
>> base class is abstract.
>>
>> So I come back to the original idea - some sort of directive that
>> tells SWIG to wrap a given method as if it were a constructor. Thus
>> I could do something like this:
>>
>> %wrap_as_constructor(Geometry::marshal_load)
>>
>> Would that have any use at all for other languages?
>>
>> Charlie
>>
>>
>> Marcelo Matus wrote:
>>
>>> Oh well, you will need to use something like
>>>
>>> %factory(geos::Geometry::from_s,....);
>>>
>>> namespace geos {
>>> %extend Geometry {
>>> static Geometry *from_s(const std::string& s) { ... }
>>> }
>>> }
>>>
>>>
>>> Marcelo
>>>
>>>
>>> Charlie
>>> Savage wrote:
>>>
>>>
>>>
>>> Charlie Savage wrote:
>>>
>>>> Okay, figured it out, user error. The Geometry class is an
>>>> abstract class, thus SWIG does not generate any constructors for
>>>> it. Sorry about the noise.
>>>>
>>>> Charlie
>>>>
>>>> Marcelo Matus wrote:
>>>>
>>>>> Did you try:
>>>>> namespace geos {
>>>>> %extend Geometry {
>>>>> Geometry(string data)
>>>>> {
>>>>> }
>>>>>
>>>>> string to_s()
>>>>> {
>>>>> ostringstream os;
>>>>> os << "<Geos::Geometry ";
>>>>> os << self->toString();
>>>>> os << ">";
>>>>> return os.str();
>>>>> }
>>>>> }
>>>>> }
>>>>>
>>>>>
>>>>> Charlie Savage wrote:
>>>>>
>>>>>>>
>>>>>>>
>>>>>>> then you can use %extend, i.e.;
>>>>>>>
>>>>>>> %extend Foo {
>>>>>>> Foo(<marshalling params>) { <do unmarshalling here>;}
>>>>>>> }
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> Hi Marcelo,
>>>>>>
>>>>>> Running into issues with this approach. Here is an extract from
>>>>>> my SWIG file:
>>>>>>
>>>>>> %extend geos::Geometry {
>>>>>> Geometry(string data)
>>>>>> {
>>>>>> }
>>>>>>
>>>>>> string to_s()
>>>>>> {
>>>>>> ostringstream os;
>>>>>> os << "<Geos::Geometry ";
>>>>>> os << self->toString();
>>>>>> os << ">";
>>>>>> return os.str();
>>>>>> }
>>>>>> }
>>>>>>
>>>>>> The generated code includes the to_s method but not the new
>>>>>> constructor:
>>>>>>
>>>>>> SWIGINTERN string geos_Geometry_to_s(geos::Geometry *self){
>>>>>> ostringstream os;
>>>>>> os << "<Geos::Geometry ";
>>>>>> os << self->toString();
>>>>>> os << ">";
>>>>>> return os.str();
>>>>>> }
>>>>>>
>>>>>> I've tried reproducing the problem on a smaller test case, but no
>>>>>> luck. I see in the test suite that extend_default works
>>>>>> fine, and when I add namespaces into the mix it still works
>>>>>> fine. Any thoughts on why the constructor wouldn't be showing
>>>>>> up? Note that the class defines some public constructors
>>>>>> already, like this:
>>>>>>
>>>>>> namespace geos {
>>>>>>
>>>>>> class Geometry{
>>>>>> public:
>>>>>> Geometry(const Geometry &geom);
>>>>>> Geometry(const GeometryFactory *factory);
>>>>>> virtual ~Geometry();
>>>>>> etc...
>>>>>> }
>>>>>>
>>>>>> Thanks,
>>>>>>
>>>>>> Charlie
>>>>>>
>>>>>>
>>>>>>>
>>>>>>> Marce;p
>>>>>>>
>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Last, Ruby objects support a clone method which maps directly
>>>>>>>>>> to C++ copy constructors. When clone is called on a Ruby
>>>>>>>>>> object that wraps a C++ object, it will call a method named
>>>>>>>>>> init_copy in C if one is defined. Currently SWIG doesn't
>>>>>>>>>> support this - C++ copy constructors are simply folded in
>>>>>>>>>> with other constructors. These all get mapped to a Ruby
>>>>>>>>>> method called initialize. It would be nice if C++ copy
>>>>>>>>>> constructors got mapped to init_copy instead since that more
>>>>>>>>>> naturally fits (for backwards compatibility you could also
>>>>>>>>>> still wrap them as part of initialize). I assume SWIG
>>>>>>>>>> internally marks copy constructors, so this would be easy
>>>>>>>>>> enough to implement?
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> In the same vein, Ruby also has built-in support for
>>>>>>>>> marshaling via YAML (like Python and Perl can), so in fact,
>>>>>>>>> you could have another static method called from_yaml or some
>>>>>>>>> such thing that also takes a string but in a much different
>>>>>>>>> format.
>>>>>>>>>
>>>>>>>>> yes, copy constructor are marked and even there is a
>>>>>>>>> 'copyconstructorHandler' method you
>>>>>>>>> can specialized.
>>>>>>>>>
>>>>>>>> Great - I'll take a look and see if I can implement this for
>>>>>>>> SWIG 1.3.30 or whatever the next release will be called.
>>>>>>>>
>>>>>>>> Charlie
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> -------------------------------------------------------
>>>>>>> This SF.Net email is sponsored by xPML, a groundbreaking
>>>>>>> scripting language
>>>>>>> that extends applications into web and mobile media. Attend the
>>>>>>> live webcast
>>>>>>> and join the prime developer group breaking into this new coding
>>>>>>> territory!
>>>>>>> http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642
>>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> -------------------------------------------------------
>>>>>> This SF.Net email is sponsored by xPML, a groundbreaking
>>>>>> scripting language
>>>>>> that extends applications into web and mobile media. Attend the
>>>>>> live webcast
>>>>>> and join the prime developer group breaking into this new coding
>>>>>> territory!
>>>>>> http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642
>>>>>>
>>>>>> _______________________________________________
>>>>>> Swig-devel mailing list
>>>>>> Swi...@li...
>>>>>> https://lists.sourceforge.net/lists/listinfo/swig-devel
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>
>>>
>>>
>
>
>
|