Still struggling to convert C++ code

I having no problem converting except for C++ code that depends an external C++ library. IMHO Rust doesnt have enough commonly used libraries to win over C++ users...One example is the RUST PNG file encoders/decodes (Rust has several but the Rust code is ridiculously complex, difficult to read, and dont seem to work). Converting C++ to Go takes much less time than converting C++ to Rust, despite Rust IMHO being the best language of the three.

Which PNG crate in particular doesn't work, and how?

Interoperability between Rust and C++ is tricky indeed. There are crates like cxx that are meant to help with that.

I maintain Rust version of lodepng which has been converted from a C project of the same name, and still passes all of the original unit tests. The other png crate passes PNG test suite, so it should be fine too.

As for readability, it really depends on what you're used to. I find Rust code much more readable than C++ code, but that's because I have more Rust experience than C++ experience.

4 Likes

not sure how low level you need to go, but the Image crate is fairly ergonomic, and works similarly to Pillow in Python.

2 Likes

To add an opposing data point, I also find Rust code more readable than C++ code, although I have more C++ experience than Rust experience.

4 Likes

I sense some ambiguity in the question.

Do you mean actually translating programs written in C++ to Rust?

I would imagine that is generally difficult to impossible depending on how much it uses C++ classes, inheritance, templates, etc, etc. But then I cannot see how converting C++ to Go would be any easier.

Or do you mean "converting yourself to C++". That is likely much easier. I have yet to be floored for the lack of useful libraries (crates) in Rust. And there is more appearing every day.

Personally I find C++ hard work to read. And the documentation is terrible. Despite having struggled with it for many years.

3 Likes

I`ve used lodepng (C++ version for many years). When I looked at the Rust version, it seemed overly complex compared to the C++ code. ...I've always preferred using only compilers to do all my building vs IDEs like VisualStudio etc. so I've always downloaded the source code files needed .... I'm wondering if this is a mistake when using Rust i.e with Rust, cargo is the only way to do things...

It is not, you can use the rustc compiler yourself by passing all required arguments. But this is what cargo already does for you, and it is an official tool. I don't see any reason to not use it.

I am using a text editor and invoking cargo in the command line myself while writing Rust code and so far it worked very well.

3 Likes

Looking at the docs for loadpng : LodePNG — Rust image library // Lib.rs the API looks simple enough that even I could use it.

I have never used IDE's. I don't see what the problem is with Cargo. It automates all that stuff you would do manually in C++: All that that finding and fetching of source for libraries and building your program, managing versions and so on. And all from the command line, excellent!

What is not to like? As noted above one need not use Cargo. Just use the compiler directly.

I don't get what is overly complex. The API is basically the same. I've only added a little tweaks like exposing State as separate Encode/Decode to avoid them having irrelevant methods.

You can use it with just couple of lines:

[dependencies]
lodepng = "3"

and

use lodepng::*; // or not even that if you prefix method calls yourself

All these projects are published as cargo packages. If you're trying to build them without Cargo, then of course it's going to be laborious and require you to know all the flags that Cargo sets. It's like downloading a cmake project and then refusing to use cmake, and trying to build it by calling gcc *.c by hand instead. That strategy works for rustc the same. You can do it, but it's a waste of time.

5 Likes

cargo isn't an IDE, so I'm confused. It makes a lot of things simpler and manages dependencies for you, but you can use any environment you like to develop. I use vim. Mostly I call the compiler through cargo but not always.

2 Likes

OK I'm convinced.. I just downloaded cargo and will try lodepng...Is it correct to say that will all future crates i use will be stored in /usr/shr/cargo ?

I'm also confused...cargo clearly is not an IDE

Yeah, cargo caches versions of crates you've already used, but copies them again to the build directory. That way you don't deal with downloading them again.

Cargo deals with compiling and linking dependencies. It passes options to the Rust compiler on how to compile the various crates (optimized, as a dependency, static library, etc.)

1 Like

Your post sounded like maybe you thought it was. Glad that's cleared up!

Thanks guys.. I really appreciate your help.... I'm much more motivated now to continue with my C++ conversion efforts.

Tried this per the lodepng crate doc

use lodepng::*;

fn main() {
println!("PNG !");

let mut state = lodepng::Decoder::new();
state.remember_unknown_chunks(true);

match state.decode("Eyes.png") {
Ok(lodepng::Image::RGB(image)) => { std::println!("RGB image !"); }
Ok(lodepng::Image::RGBA(image)) => { std::println!("RGBA image !");}
Ok(lodepng::Image::RGBA16(image)) => { std::println!("RGBA16 image !");}
Ok(lodepng::Image::Gray(image)) => { println!("GRAY image !");}
Ok(_) => { println!("unknown image !");}
Err(err) => { println!("ERROR");}
}

for chunk in state.info_png().unknown_chunks() {
println!("{:?} = {:?}", chunk.name(), chunk.data());
}

// Color profile (to be used with e.g. LCMS2)
let icc_data = state.info_png().get_icc();
}

output

$cargo check
Checking PNG v0.1.0 (/home/D6204/PNG)
warning: unused import: lodepng::*
--> src/main.rs:1:5

1 | use lodepng::*; // or you can prefix method calls yourself

^^^^^^^^^^

= note: #[warn(unused_imports)] on by default

error[E0599]: no variant or associated item named Gray found for type lodepng::Image in the current scope
--> src/main.rs:13:24

13 | Ok(lodepng::Image::Gray(image)) => { println!("GRAY image !");}

^^^^

variant or associated item not found in lodepng::Image
help: there is a variant with a similar name: Grey

error[E0061]: this function takes 1 parameter but 0 parameters were supplied

for chunk in state.info_png().unknown_chunks() {

^^^^^^^^^^^^^^ expected 1 parameter

error[E0599]: no method named get_icc found for type &lodepng::ffi::Info in the current scope
--> src/main.rs:23:33

23 | let icc_data = state.info_png().get_icc();

It looks like the example in the README is out of date.

error[E0599]: no variant or associated item named Gray found for type lodepng::Image in the current scope
help: there is a variant with a similar name: Grey

Note the spelling change.

error[E0061]: this function takes 1 parameter but 0 parameters were supplied

for chunk in state.info_png().unknown_chunks() {
                              ^^^^^^^^^^^^^^ expected 1 parameter

According to the latest docs, this method takes a ChunkPosition parameter. I'm not sure what value you should pass here.

error[E0599]: no method named get_icc found for type &lodepng::ffi::Info in the current scope

It looks like this method has moved to Decoder, so this should change to:

let icc_data = state.get_icc();

Looks like crate lodepng has two shades of Gray !