Qt5 Rust bindings and general C++ to Rust bindings feedback

classic Classic list List threaded Threaded
13 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Qt5 Rust bindings and general C++ to Rust bindings feedback

Alexander Tsvyashchenko
 

Hi All,

Recently I was playing with bindings generator from C++ to Rust. I
managed to make things work for Qt5 wrapping, but stumbled into multiple
issues along the way.

I tried to summarize my "pain points" in the following blog post:
http://endl.ch/content/cxx2rust-pains-wrapping-c-rust-example-qt5 

I hope that others might benefit from my experience and that some of
these "pain points" can be fixed in Rust.

I'll try to do my best in answering questions / acting on feedback, if
any, but I have very limited amount of free time right now so sorry in
advance if answers take some time.

Thanks!

--
Good luck! Alexander
 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20140522/5fba8dcb/attachment.html>

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Qt5 Rust bindings and general C++ to Rust bindings feedback

Patrick Walton
You can use "extern "Rust" fn" (or ||:'static) to achieve something like C++03 member function pointers without the lifetimes. Attacking Rust without asking first how to do this is unappreciated.

In the future, unboxed closures will make callbacks easier.

I am opposed to function overloading and default parameters. I do not see it as a burden to define meaningful unique function names. On the contrary, this helps greppability in large codebases.

Patrick

On May 22, 2014 1:27:42 PM PDT, Alexander Tsvyashchenko <ndl at endl.ch> wrote:

>
>
>Hi All,
>
>Recently I was playing with bindings generator from C++ to Rust. I
>managed to make things work for Qt5 wrapping, but stumbled into
>multiple
>issues along the way.
>
>I tried to summarize my "pain points" in the following blog post:
>http://endl.ch/content/cxx2rust-pains-wrapping-c-rust-example-qt5 
>
>I hope that others might benefit from my experience and that some of
>these "pain points" can be fixed in Rust.
>
>I'll try to do my best in answering questions / acting on feedback, if
>any, but I have very limited amount of free time right now so sorry in
>advance if answers take some time.
>
>Thanks!
>
>--
>Good luck! Alexander
>
>
>------------------------------------------------------------------------
>
>_______________________________________________
>Rust-dev mailing list
>Rust-dev at mozilla.org
>https://mail.mozilla.org/listinfo/rust-dev

--
Sent from my Android phone with K-9 Mail. Please excuse my brevity.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20140522/1968d142/attachment.html>

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Qt5 Rust bindings and general C++ to Rust bindings feedback

Corey Richardson
In reply to this post by Alexander Tsvyashchenko
Given the size of the binaries it looks like you may not have been
passing -O, which often gives the best code size.

On Thu, May 22, 2014 at 1:27 PM, Alexander Tsvyashchenko <ndl at endl.ch> wrote:

> Hi All,
>
> Recently I was playing with bindings generator from C++ to Rust. I managed
> to make things work for Qt5 wrapping, but stumbled into multiple issues
> along the way.
>
> I tried to summarize my "pain points" in the following blog post:
> http://endl.ch/content/cxx2rust-pains-wrapping-c-rust-example-qt5
>
> I hope that others might benefit from my experience and that some of these
> "pain points" can be fixed in Rust.
>
> I'll try to do my best in answering questions / acting on feedback, if any,
> but I have very limited amount of free time right now so sorry in advance if
> answers take some time.
>
> Thanks!
>
> --
> Good luck!                                     Alexander
>
>
> _______________________________________________
> Rust-dev mailing list
> Rust-dev at mozilla.org
> https://mail.mozilla.org/listinfo/rust-dev
>



--
http://octayn.net/

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Qt5 Rust bindings and general C++ to Rust bindings feedback

Huon Wilson
In reply to this post by Alexander Tsvyashchenko
Hi Alexander,

I wrote up some feedback and tried to post it on your blog, but
unfortunately submitting a comment was failing with an nginx error, so I
posted it on /r/rust instead:
http://www.reddit.com/r/rust/comments/269t6i/cxx2rust_the_pains_of_wrapping_c_in_rust_on_the/


(It's good to see people experimenting with GUI frameworks in Rust!)


Huon


On 23/05/14 06:27, Alexander Tsvyashchenko wrote:

>
> Hi All,
>
> Recently I was playing with bindings generator from C++ to Rust. I
> managed to make things work for Qt5 wrapping, but stumbled into
> multiple issues along the way.
>
> I tried to summarize my "pain points" in the following blog
> post: http://endl.ch/content/cxx2rust-pains-wrapping-c-rust-example-qt5
>
> I hope that others might benefit from my experience and that some of
> these "pain points" can be fixed in Rust.
>
> I'll try to do my best in answering questions / acting on feedback, if
> any, but I have very limited amount of free time right now so sorry in
> advance if answers take some time.
>
> Thanks!
>
> --
> Good luck!                                     Alexander
>
>
> _______________________________________________
> Rust-dev mailing list
> Rust-dev at mozilla.org
> https://mail.mozilla.org/listinfo/rust-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20140523/4c5bf1c0/attachment.html>

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Qt5 Rust bindings and general C++ to Rust bindings feedback

Benjamin Striegel
In reply to this post by Patrick Walton
On Fri, May 23, 2014 at 12:12 AM, Patrick Walton <pwalton at mozilla.com>wrote:

>  You can use "extern "Rust" fn" (or ||:'static) to achieve something like
> C++03 member function pointers without the lifetimes. Attacking Rust
> without asking first how to do this is unappreciated.
>

I think that characterizing this as an "attack" is in bad faith. This is a
very impressive and insightful post. Alexander is a member of our primary
demographic, and it is immensely valuable to get real-world feedback on how
C++ users will receive the language when employing it for non-trivial
projects.

If there is a misunderstanding over some of Rust's features, then it is a
documentation deficiency that needs to be addressed. The fact that
Alexander took the effort to post this here at all shows that he wants to
understand the language, not to bash it. If only every blogger was so
considerate!

So thank you, Alexander. I hope that you found Rust enjoyable despite its
current rough edges! I'd love it if you kept an eye on the language as it
develops, and I'd be delighted to read a follow-up post incorporating the
feedback from here and from reddit.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20140523/00590882/attachment.html>

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Qt5 Rust bindings and general C++ to Rust bindings feedback

Alexander Tsvyashchenko
In reply to this post by Patrick Walton
 

Hi Patrick,

Thanks for your answer! See comments below.

On 2014-05-23 06:12, Patrick Walton wrote:

> You can use "extern "Rust" fn" (or ||:'static) to achieve something like C++03 member function pointers without the lifetimes.

Do I understand correctly that by "extern "Rust" fn" you mean taking the
pointer to the global function? If yes, then I'm definitely aware of the
possibility to do that, but it is not helpful in the context of signals
/ slots. Please see my Reddit comment for more detailed explanation:
http://www.reddit.com/r/rust/comments/269t6i/cxx2rust_the_pains_of_wrapping_c_in_rust_on_the/chpfi1o


RE: (||:'static) - as you can see in my initial post, this is what I
ended up using - only without the explicit 'static annotation, but with
the same restriction of not having any captured state.

I agree that from what I've seen so far, ||:'static seems to be the
closest thing to member function pointers - but I'd argue it's still not
the full replacement as it's more verbose - that is, requires explicitly
passing the state + declaring & forwarding all function arguments, e.g.
instead of "slot(&obj, &Class::method)" it's "slot(&obj, |obj, arg1,
arg2, arg3, arg4, arg5, arg6, arg7| { obj.method(arg1, arg2, arg3, arg4,
arg5, arg6, arg7) })".

And yes, there are signals with up to 7 arguments in Qt5 ;-)

> I am opposed to function overloading and default parameters. I do not see it as a burden to define meaningful unique function names. On the contrary, this helps greppability in large codebases.

Yes, I do realize there are quite strong opinions regarding function
overloading and default parameters within Rust development community. I
hold strong opinions on this subject too, and these happen to be the
opposite ones to what you have - which is the perfect background to
start flame war, which I have zero interest in ;-)

Therefore, I suggest we move from the question "are function overloading
and default parameters good or bad?" to the question "Lots of existing
C++ libraries use function overloading and default parameters. How Rust
should deal with wrapping these?"

I believe the answer to this question is important because with all the
optimism around Rust adoption, I doubt all existing C++ libraries that
were developed over the last decades (Qt including) will be magically
re-implemented in Rust within the next year or two.

So far I can imagine several possible answers:

        * "We don't care, your legacy C++ libraries are bad and you should feel
bad!" - I think this stance would be bad for Rust and would hinder its
adoption, but if that's the ultimate answer - I'd personally prefer it
said loud and clear, so that at least nobody has any illusions.

        * "Define & maintain the mapping between C++ and Rust function names"
(I assume this is what you're alluding to with "define meaningful unique
function names" above?) While this might be possible for smaller
libraries, this is out of the question for large libraries like Qt5 - at
least I won't create and maintain this mapping for sure, and I doubt
others will: just looking at the stats from 3 Qt5 libraries (QtCore,
QtGui and QtWidgets) out of ~30 Qt libraries in total, from the 50745
wrapped methods 9601 were overloads and required renaming.

Besides that, this has a disadvantage of throwing away majority of the
experience people have with particular library and forcing them to
le-learn its API.

On top of that, not for every overload it's easy to come up with short,
meaningful, memorable and distinctive names - you can try that exercise
for http://qt-project.org/doc/qt-4.8/qpainter.html#fillRect ;-)

        * "Come up with some way to allow overloading / default parameters" -
possibly with reduced feature set, i.e. if type inference is difficult
in the presence of overloads, as suggested in some overloads discussions
(although not unsolvable, as proven by other languages that allow both
type inference & overloading?), possibly exclude overloads from the type
inference by annotating overloaded methods with special attributes?

  * Possibly some other options I'm missing?

--
Good luck! Alexander
 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20140523/172e445a/attachment.html>

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Qt5 Rust bindings and general C++ to Rust bindings feedback

Alexander Tsvyashchenko
In reply to this post by Benjamin Striegel
 

Hi Benjamin,

Thanks for the support and encouragement!

After spending days (evenings to be more precise ;-) wrestling with the
compiler & trying different workarounds to implement at least some form
of Qt5 bindings it's possible there's some frustration present in the
post, but as explicitly stated - I definitely didn't have in mind to
"attack" / "bash" anyone or anything, so if that was the impression my
post creates - I do apologize for that!

I've got some great feedback already (especially WRT enums / flags
wrapping) that I'm going to incorporate in bindings generation.

Also, as soon as Rust has unboxed closures support, I'll definitely try
to experiment with these in the bindings to get to the nicer and safer
signals / slots implementation.

On 2014-05-23 20:26, Benjamin Striegel wrote:

> On Fri, May 23, 2014 at 12:12 AM, Patrick Walton <pwalton at mozilla.com> wrote:
>
>> You can use "extern "Rust" fn" (or ||:'static) to achieve something like C++03 member function pointers without the lifetimes. Attacking Rust without asking first how to do this is unappreciated.
>
> I think that characterizing this as an "attack" is in bad faith. This is a very impressive and insightful post. Alexander is a member of our primary demographic, and it is immensely valuable to get real-world feedback on how C++ users will receive the language when employing it for non-trivial projects.
>
> If there is a misunderstanding over some of Rust's features, then it is a documentation deficiency that needs to be addressed. The fact that Alexander took the effort to post this here at all shows that he wants to understand the language, not to bash it. If only every blogger was so considerate!
>
> So thank you, Alexander. I hope that you found Rust enjoyable despite its current rough edges! I'd love it if you kept an eye on the language as it develops, and I'd be delighted to read a follow-up post incorporating the feedback from here and from reddit.
>
> _______________________________________________
> Rust-dev mailing list
> Rust-dev at mozilla.org
> https://mail.mozilla.org/listinfo/rust-dev [1]

--
Good luck! Alexander
 

Links:
------
[1] https://mail.mozilla.org/listinfo/rust-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20140523/40576339/attachment.html>

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Qt5 Rust bindings and general C++ to Rust bindings feedback

Noam Yorav-Raphael
In reply to this post by Alexander Tsvyashchenko
You can achieve overloading which is equivalent to C++ by defining a trait
for all the types a specific argument can get:

```
enum IntOrFloatEnum {
    Int,
    F64,
}

trait IntOrFloat {
    fn get_type(&self) -> IntOrFloatEnum;
    fn get_int(self) -> int { fail!(); }
    fn get_f64(self) -> f64 { fail!(); }
}

impl IntOrFloat for int {
    fn get_type(&self) -> IntOrFloatEnum { Int }
    fn get_int(self) -> int { self }
}

impl IntOrFloat for f64 {
    fn get_type(&self) -> IntOrFloatEnum { F64 }
    fn get_f64(self) -> f64 { self }
}

fn overloaded<T: IntOrFloat>(x: T) {
    match x.get_type() {
        Int => println!("got int: {}", x.get_int()),
        F64 => println!("got f64: {}", x.get_f64()),
    }
}

fn main() {
    overloaded(5i); // prints: got int: 5
    overloaded(3.5); // prints: got f64: 3.5
}
```

This is equivalent to having to functions, overloaded(int) and
overloaded(f64). From what I see, the compiler even optimizes away the
logic, so the generated code is actually equivalent to this:

```
fn overloaded_int(x: int) { println!("got int: {}", x); }
fn overloaded_f64(x: f64) { println!("got f64: {}", x); }
fn main() {
    overloaded_int(5i);
    overloaded_f64(3.5);
}
```

(I actually think that if Rust gains one day some support for overloading,
it should be syntactic sugar for the above, which will allow you to define
a function whose argument can be of multiple types. I don't like the C++
style of defining several different functions with the same name and
letting the compiler choose which function should actually be called).

Using this method you can solve both the problem of overloading and default
arguments. For every possible number of arguments that C++ would allow,
define a function funcN<T0, T1, TN-1>(arg0: T0, arg1: T1, ..., argN-1:
TN-1). The function would check the actual types of the arguments and call
the right C++ function, filling default arguments on the way. So the only
difference between C++ and Rust code would be that you'd have to add the
number of arguments to the method name.

It would probably not be easy to generate the required code, but I think it
would solve the problem perfectly.

Cheers,
Noam


On Thu, May 22, 2014 at 11:27 PM, Alexander Tsvyashchenko <ndl at endl.ch>
wrote:

>  Hi All,
>
> Recently I was playing with bindings generator from C++ to Rust. I managed
> to make things work for Qt5 wrapping, but stumbled into multiple issues
> along the way.
>
> I tried to summarize my "pain points" in the following blog post:
> http://endl.ch/content/cxx2rust-pains-wrapping-c-rust-example-qt5
>
> I hope that others might benefit from my experience and that some of these
> "pain points" can be fixed in Rust.
>
> I'll try to do my best in answering questions / acting on feedback, if
> any, but I have very limited amount of free time right now so sorry in
> advance if answers take some time.
>
> Thanks!
>
> --
> Good luck!                                     Alexander
>
>
> _______________________________________________
> Rust-dev mailing list
> Rust-dev at mozilla.org
> https://mail.mozilla.org/listinfo/rust-dev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20140611/215697a8/attachment.html>

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Qt5 Rust bindings and general C++ to Rust bindings feedback

Kevin Cantu
Noam, that's awesome.  It even works for tuples like so (I didn't think it
would):

```
enum AaBbEnum {
    Aa,
    Bb,
}

trait AaBb {
    fn get_type(&self) -> AaBbEnum;
    fn get_aa(self) -> (int, f64) { fail!(); }
    fn get_bb(self) -> (f64) { fail!(); }
}

impl AaBb for (int, f64) {
    fn get_type(&self) -> AaBbEnum { Aa }
    fn get_aa(self) -> (int, f64) { self }
}

impl AaBb for (f64) {
    fn get_type(&self) -> AaBbEnum { Bb }
    fn get_bb(self) -> (f64) { self }
}

#[cfg(not(test))]
fn overloaded<T: AaBb>(x: T) {
    match x.get_type() {
        Aa => println!("got Aa: {}", x.get_aa()),
        Bb => println!("got Bb: {}", x.get_bb()),
    }
}

fn overloaded_format<T: AaBb>(x: T) -> String {
    match x.get_type() {
        Aa => format!("got Aa: {}", x.get_aa()),
        Bb => format!("got Bb: {}", x.get_bb()),
    }
}

#[cfg(not(test))]
#[main]
fn main() {
    overloaded((5i, 7.3243)); // prints: got Aa: (5, 7.3243)
    overloaded((3.5)); // prints: got Bb: 3.5
}

#[test]
fn overloaded_with_same_return_works() {
    // now with a shared return
    let x: String = overloaded_format((5i, 7.3243));
    let y: String = overloaded_format((3.5));
    assert_eq!(x, "got Aa: (5, 7.3243)".to_string());
    assert_eq!(y, "got Bb: 3.5".to_string());
}
```

I imagine if the functions being overloaded have different return types,
this gets uglier to use, but this is pretty good!


Kevin


On Wed, Jun 11, 2014 at 4:35 AM, Noam Yorav-Raphael <noamraph at gmail.com>
wrote:

> You can achieve overloading which is equivalent to C++ by defining a trait
> for all the types a specific argument can get:
>
> ```
> enum IntOrFloatEnum {
>     Int,
>     F64,
> }
>
> trait IntOrFloat {
>     fn get_type(&self) -> IntOrFloatEnum;
>     fn get_int(self) -> int { fail!(); }
>     fn get_f64(self) -> f64 { fail!(); }
> }
>
> impl IntOrFloat for int {
>     fn get_type(&self) -> IntOrFloatEnum { Int }
>     fn get_int(self) -> int { self }
> }
>
> impl IntOrFloat for f64 {
>     fn get_type(&self) -> IntOrFloatEnum { F64 }
>     fn get_f64(self) -> f64 { self }
> }
>
> fn overloaded<T: IntOrFloat>(x: T) {
>     match x.get_type() {
>         Int => println!("got int: {}", x.get_int()),
>         F64 => println!("got f64: {}", x.get_f64()),
>     }
> }
>
> fn main() {
>     overloaded(5i); // prints: got int: 5
>     overloaded(3.5); // prints: got f64: 3.5
> }
> ```
>
> This is equivalent to having to functions, overloaded(int) and
> overloaded(f64). From what I see, the compiler even optimizes away the
> logic, so the generated code is actually equivalent to this:
>
> ```
> fn overloaded_int(x: int) { println!("got int: {}", x); }
> fn overloaded_f64(x: f64) { println!("got f64: {}", x); }
> fn main() {
>     overloaded_int(5i);
>     overloaded_f64(3.5);
> }
> ```
>
> (I actually think that if Rust gains one day some support for overloading,
> it should be syntactic sugar for the above, which will allow you to define
> a function whose argument can be of multiple types. I don't like the C++
> style of defining several different functions with the same name and
> letting the compiler choose which function should actually be called).
>
> Using this method you can solve both the problem of overloading and
> default arguments. For every possible number of arguments that C++ would
> allow, define a function funcN<T0, T1, TN-1>(arg0: T0, arg1: T1, ...,
> argN-1: TN-1). The function would check the actual types of the arguments
> and call the right C++ function, filling default arguments on the way. So
> the only difference between C++ and Rust code would be that you'd have to
> add the number of arguments to the method name.
>
> It would probably not be easy to generate the required code, but I think
> it would solve the problem perfectly.
>
> Cheers,
> Noam
>
>
> On Thu, May 22, 2014 at 11:27 PM, Alexander Tsvyashchenko <ndl at endl.ch>
> wrote:
>
>>  Hi All,
>>
>> Recently I was playing with bindings generator from C++ to Rust. I
>> managed to make things work for Qt5 wrapping, but stumbled into multiple
>> issues along the way.
>>
>> I tried to summarize my "pain points" in the following blog post:
>> http://endl.ch/content/cxx2rust-pains-wrapping-c-rust-example-qt5
>>
>> I hope that others might benefit from my experience and that some of
>> these "pain points" can be fixed in Rust.
>>
>> I'll try to do my best in answering questions / acting on feedback, if
>> any, but I have very limited amount of free time right now so sorry in
>> advance if answers take some time.
>>
>> Thanks!
>>
>> --
>> Good luck!                                     Alexander
>>
>>
>> _______________________________________________
>> Rust-dev mailing list
>> Rust-dev at mozilla.org
>> https://mail.mozilla.org/listinfo/rust-dev
>>
>>
>
> _______________________________________________
> Rust-dev mailing list
> Rust-dev at mozilla.org
> https://mail.mozilla.org/listinfo/rust-dev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20140611/628d45a7/attachment.html>

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Qt5 Rust bindings and general C++ to Rust bindings feedback

Noam Yorav-Raphael
Thanks!

I looked at http://qt-project.org/doc/qt-4.8/qwidget.html, which has
several overloaded functions, and didn't find overloaded functions with
different return types. If there are, there are probably rare - I really
think that overloaded functions with different return types are an
abomination.



On Wed, Jun 11, 2014 at 8:23 PM, Kevin Cantu <me at kevincantu.org> wrote:

> Noam, that's awesome.  It even works for tuples like so (I didn't think it
> would):
>
> ```
> enum AaBbEnum {
>     Aa,
>     Bb,
> }
>
> trait AaBb {
>     fn get_type(&self) -> AaBbEnum;
>     fn get_aa(self) -> (int, f64) { fail!(); }
>     fn get_bb(self) -> (f64) { fail!(); }
> }
>
> impl AaBb for (int, f64) {
>     fn get_type(&self) -> AaBbEnum { Aa }
>     fn get_aa(self) -> (int, f64) { self }
> }
>
> impl AaBb for (f64) {
>     fn get_type(&self) -> AaBbEnum { Bb }
>     fn get_bb(self) -> (f64) { self }
> }
>
> #[cfg(not(test))]
> fn overloaded<T: AaBb>(x: T) {
>     match x.get_type() {
>         Aa => println!("got Aa: {}", x.get_aa()),
>         Bb => println!("got Bb: {}", x.get_bb()),
>     }
> }
>
> fn overloaded_format<T: AaBb>(x: T) -> String {
>     match x.get_type() {
>         Aa => format!("got Aa: {}", x.get_aa()),
>         Bb => format!("got Bb: {}", x.get_bb()),
>     }
> }
>
> #[cfg(not(test))]
> #[main]
> fn main() {
>     overloaded((5i, 7.3243)); // prints: got Aa: (5, 7.3243)
>     overloaded((3.5)); // prints: got Bb: 3.5
> }
>
> #[test]
> fn overloaded_with_same_return_works() {
>     // now with a shared return
>     let x: String = overloaded_format((5i, 7.3243));
>     let y: String = overloaded_format((3.5));
>     assert_eq!(x, "got Aa: (5, 7.3243)".to_string());
>     assert_eq!(y, "got Bb: 3.5".to_string());
> }
> ```
>
> I imagine if the functions being overloaded have different return types,
> this gets uglier to use, but this is pretty good!
>
>
> Kevin
>
>
> On Wed, Jun 11, 2014 at 4:35 AM, Noam Yorav-Raphael <noamraph at gmail.com>
> wrote:
>
>> You can achieve overloading which is equivalent to C++ by defining a
>> trait for all the types a specific argument can get:
>>
>> ```
>> enum IntOrFloatEnum {
>>     Int,
>>     F64,
>> }
>>
>> trait IntOrFloat {
>>     fn get_type(&self) -> IntOrFloatEnum;
>>     fn get_int(self) -> int { fail!(); }
>>     fn get_f64(self) -> f64 { fail!(); }
>> }
>>
>> impl IntOrFloat for int {
>>     fn get_type(&self) -> IntOrFloatEnum { Int }
>>     fn get_int(self) -> int { self }
>> }
>>
>> impl IntOrFloat for f64 {
>>     fn get_type(&self) -> IntOrFloatEnum { F64 }
>>     fn get_f64(self) -> f64 { self }
>> }
>>
>> fn overloaded<T: IntOrFloat>(x: T) {
>>     match x.get_type() {
>>         Int => println!("got int: {}", x.get_int()),
>>         F64 => println!("got f64: {}", x.get_f64()),
>>     }
>> }
>>
>> fn main() {
>>     overloaded(5i); // prints: got int: 5
>>     overloaded(3.5); // prints: got f64: 3.5
>> }
>> ```
>>
>> This is equivalent to having to functions, overloaded(int) and
>> overloaded(f64). From what I see, the compiler even optimizes away the
>> logic, so the generated code is actually equivalent to this:
>>
>> ```
>> fn overloaded_int(x: int) { println!("got int: {}", x); }
>> fn overloaded_f64(x: f64) { println!("got f64: {}", x); }
>> fn main() {
>>     overloaded_int(5i);
>>     overloaded_f64(3.5);
>> }
>> ```
>>
>> (I actually think that if Rust gains one day some support for
>> overloading, it should be syntactic sugar for the above, which will allow
>> you to define a function whose argument can be of multiple types. I don't
>> like the C++ style of defining several different functions with the same
>> name and letting the compiler choose which function should actually be
>> called).
>>
>> Using this method you can solve both the problem of overloading and
>> default arguments. For every possible number of arguments that C++ would
>> allow, define a function funcN<T0, T1, TN-1>(arg0: T0, arg1: T1, ...,
>> argN-1: TN-1). The function would check the actual types of the arguments
>> and call the right C++ function, filling default arguments on the way. So
>> the only difference between C++ and Rust code would be that you'd have to
>> add the number of arguments to the method name.
>>
>> It would probably not be easy to generate the required code, but I think
>> it would solve the problem perfectly.
>>
>> Cheers,
>> Noam
>>
>>
>> On Thu, May 22, 2014 at 11:27 PM, Alexander Tsvyashchenko <ndl at endl.ch>
>> wrote:
>>
>>>   Hi All,
>>>
>>> Recently I was playing with bindings generator from C++ to Rust. I
>>> managed to make things work for Qt5 wrapping, but stumbled into multiple
>>> issues along the way.
>>>
>>> I tried to summarize my "pain points" in the following blog post:
>>> http://endl.ch/content/cxx2rust-pains-wrapping-c-rust-example-qt5
>>>
>>> I hope that others might benefit from my experience and that some of
>>> these "pain points" can be fixed in Rust.
>>>
>>> I'll try to do my best in answering questions / acting on feedback, if
>>> any, but I have very limited amount of free time right now so sorry in
>>> advance if answers take some time.
>>>
>>> Thanks!
>>>
>>> --
>>> Good luck!                                     Alexander
>>>
>>>
>>> _______________________________________________
>>> Rust-dev mailing list
>>> Rust-dev at mozilla.org
>>> https://mail.mozilla.org/listinfo/rust-dev
>>>
>>>
>>
>> _______________________________________________
>> Rust-dev mailing list
>> Rust-dev at mozilla.org
>> https://mail.mozilla.org/listinfo/rust-dev
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20140611/9642ddfe/attachment.html>

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Qt5 Rust bindings and general C++ to Rust bindings feedback

Kevin Cantu
In reply to this post by Kevin Cantu
Matthew Monrocq suggests this improvement, which looks even cleaner to use,
although slightly more complicated to implement generation of:


On Wed, Jun 11, 2014 at 11:38 AM, Matthieu Monrocq <
matthieu.monrocq at gmail.com> wrote:

> [snip]
>
> I do like the idea of the trait, however I would rather do away with all
> the `get_aa`: why not directly wrap the parameters ?
>
>     enum AaBbEnum {
>         Aa(int, f64),
>         Bb(f64),
>     }
>     trait AaBb {
>         fn get(&self) -> AaBbEnum;
>
>     }
>
>     impl AaBb for (int, f64) {
>         fn get(&self) -> AaBbEnum { match *self { (i, f) => Aa(i, f), } }
>     }
>
>     impl AaBb for (f64) {
>         fn get(&self) -> AaBbEnum { Bb(*self) }
>
>     }
>
>     fn overloaded<T: AaBb>(x: T) {
>         match x.get() {
>             Aa(i, f) => println!("got Aa: {}", (i, f)),
>             Bb(f) => println!("got Bb: {}", f),
>
>         }
>     }
>
>     #[main]
>     fn main() {
>         overloaded((5i, 7.3243)); // prints: got Aa: (5, 7.3243)
>         overloaded((3.5)); // prints: got Bb: 3.5
>     }
>
> Now, there is no runtime failure => you cannot accidentally match on `Bb`
> and requests `get_aa`!
>



Kevin
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20140611/04529400/attachment.html>

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Qt5 Rust bindings and general C++ to Rust bindings feedback

Noam Yorav-Raphael
Cool. I was afraid that it will be harder for the compiler to optimize away
the enum, but it seems to be doing fine.
(If it does turn out that it's harder for the compiler, I don't see a real
problem with the approach I suggested, as a runtime failure can only be
caused by a bug in the code generator, not by user code)


On Thu, Jun 12, 2014 at 2:13 AM, Kevin Cantu <me at kevincantu.org> wrote:

> Matthew Monrocq suggests this improvement, which looks even cleaner to
> use, although slightly more complicated to implement generation of:
>
>
> On Wed, Jun 11, 2014 at 11:38 AM, Matthieu Monrocq <
> matthieu.monrocq at gmail.com> wrote:
>
>> [snip]
>>
>> I do like the idea of the trait, however I would rather do away with all
>> the `get_aa`: why not directly wrap the parameters ?
>>
>>     enum AaBbEnum {
>>         Aa(int, f64),
>>         Bb(f64),
>>     }
>>     trait AaBb {
>>         fn get(&self) -> AaBbEnum;
>>
>>     }
>>
>>     impl AaBb for (int, f64) {
>>         fn get(&self) -> AaBbEnum { match *self { (i, f) => Aa(i, f), } }
>>     }
>>
>>     impl AaBb for (f64) {
>>         fn get(&self) -> AaBbEnum { Bb(*self) }
>>
>>     }
>>
>>     fn overloaded<T: AaBb>(x: T) {
>>         match x.get() {
>>             Aa(i, f) => println!("got Aa: {}", (i, f)),
>>             Bb(f) => println!("got Bb: {}", f),
>>
>>         }
>>     }
>>
>>     #[main]
>>     fn main() {
>>         overloaded((5i, 7.3243)); // prints: got Aa: (5, 7.3243)
>>         overloaded((3.5)); // prints: got Bb: 3.5
>>     }
>>
>> Now, there is no runtime failure => you cannot accidentally match on `Bb`
>> and requests `get_aa`!
>>
>
>
>
> Kevin
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20140612/fbb49448/attachment.html>

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Qt5 Rust bindings and general C++ to Rust bindings feedback

techabc
https://github.com/cyndis/qmlrs

qmlrs - QtQuick bindings for Rust

but , still hope qt5 binding for rust.

2014-06-12 14:25 GMT+08:00 Noam Yorav-Raphael <[hidden email]>:
Cool. I was afraid that it will be harder for the compiler to optimize away the enum, but it seems to be doing fine.
(If it does turn out that it's harder for the compiler, I don't see a real problem with the approach I suggested, as a runtime failure can only be caused by a bug in the code generator, not by user code)


On Thu, Jun 12, 2014 at 2:13 AM, Kevin Cantu <[hidden email]> wrote:
Matthew Monrocq suggests this improvement, which looks even cleaner to use, although slightly more complicated to implement generation of:


On Wed, Jun 11, 2014 at 11:38 AM, Matthieu Monrocq <[hidden email]> wrote:
[snip]

I do like the idea of the trait, however I would rather do away with all the `get_aa`: why not directly wrap the parameters ?

    enum AaBbEnum {
        Aa(int, f64),
        Bb(f64),
    }
    trait AaBb {
        fn get(&self) -> AaBbEnum;

    }

    impl AaBb for (int, f64) {
        fn get(&self) -> AaBbEnum { match *self { (i, f) => Aa(i, f), } }
    }

    impl AaBb for (f64) {
        fn get(&self) -> AaBbEnum { Bb(*self) }

    }
   
    fn overloaded<T: AaBb>(x: T) {
        match x.get() {
            Aa(i, f) => println!("got Aa: {}", (i, f)),
            Bb(f) => println!("got Bb: {}", f),

        }
    }
   
    #[main]
    fn main() {
        overloaded((5i, 7.3243)); // prints: got Aa: (5, 7.3243)
        overloaded((3.5)); // prints: got Bb: 3.5
    }

Now, there is no runtime failure => you cannot accidentally match on `Bb` and requests `get_aa`!



Kevin 



_______________________________________________
Rust-dev mailing list
[hidden email]
https://mail.mozilla.org/listinfo/rust-dev



_______________________________________________
Rust-dev mailing list
[hidden email]
https://mail.mozilla.org/listinfo/rust-dev
Loading...