How do I determine my Windows OS version with Rust? - rust

Can I use cfg to determine the OS Windows version for this block of code? The thing is that shcore lib is not available in windows 7 and below
#[cfg(all(windows, not(feature = "inline")))]
unsafe {
winapi::um::shellscalingapi::SetProcessDpiAwareness(2);
}

Related

How can I get a relative path in Rust?

I want to create a program and compile it to WASM. The program runs on Windows and Unix.
The program generates a relative path for a filename from the given base_path and converts it to posix:
use pathdiff::diff_paths;
let relative_filename = diff_paths(filename, base_path).unwrap();
let path_parts = relative_filename.components().map(|component| component.as_os_str().to_str().unwrap()).collect::<Vec<&str>>();
let relative_posix_path = path_parts.join("/");
I thought this would allow me to generate a consistent relative path for both systems for example:
/// e.g. "/foo/", "/bar/baz.txt" -> "../bar/baz.txt"
/// e.g. "C:\foo\", "C:\foo\baz.txt" -> "../bar/baz.txt"
Unfortunately when compiled to WASM it seems not to be able to parse Windows file paths anymore.
Is there a cross platform way to handle paths in rust?

Using `syscall.LINUX_REBOOT_CMD_POWER_OFF` when programming on windows for linux

I'm developing code using Golang on windows as it is easier for testing purposes, but the final bin should run on a raspberry pi.
I need to call syscall.Reboot(syscall.LINUX_REBOOT_CMD_POWER_OFF) which works fine however, I need to comment it out on windows to test the binary and uncomment it when building in on the rpi.
Even if I test the os to determine if the function is called, since it does not seem to exist on windows, go won't build it.
Is there a way to build the code on windows even though this function doesn't exist?
I do not wish to do any code edits on the rpi, and i cannot use the wsl i need to communicate with usb devices and such which is easier when building on the native os
It sounds like you want conditional compilation as described here:
https://blog.ralch.com/articles/golang-conditional-compilation/
You could have two source files in your package that use the _os nomenclature as the name. Both files export a function that does the appropriate behavior.
reboot_linux.go
package main
import "syscall"
func Reboot() {
syscall.Reboot(syscall.LINUX_REBOOT_CMD_POWER_OFF)
}
reboot_windows.go
package main
import "fmt"
func Reboot() {
fmt.Println("A reboot would have occurred")
}
When you do go build it won't compile reboot_linux.go on Windows. Nor will it compile reboot_windows.go on Linux.
Interestingly enough - this is exactly how Go separates out the implementations of the syscall package in its own source code.

Can not create rust library for python

I am trying to make a python module in rust. I am continuing to fail to get the files that I need to generate. I followed this tutorial almost exactly.
https://mycognosist.github.io/tutorial-rust-python-lib.html
Here is my toml file.
name = "pylib"
version = "0.1.0"
authors = ["Atops"]
edition = "2018"
[lib]
name = "status"
crate-type = ["cdylib"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies.cpython]
version = "0.5"
features = ["extension-module"]
Here is the code for lib.rs
extern crate cpython;
use cpython::{PyResult, Python, py_fn, py_module_initializer};
pub extern fn hello(_py: Python, val: String) -> PyResult<String> {
match &*val {
"hello" => Ok("world".to_string()),
_ => Ok("afdfs".to_string()),
}
}
py_module_initializer!(status, initstatus, Pyinit_status, |py, m|{
m.add(py, "__doc__", "asdhgdfs")?;
m.add(py, "hello", py_fn!(py, hello(val: String)))?;
Ok(())
});
I navigate to the appropriate folder with my cargo.toml file and use cargo build --release, as specified in the tutorial. It finishes with a few warnings about certain things being "not FFI-safe". When it finishes a new folder is created called "target". I go through there to where the files for the library should be, but the appropriate files don't seem to have been generated. I have these.
target\release
These don't seem to be usable for me. I am not sure what I have done wrong.
I copied every single one of these files to another folder and tried importing them in python. This did not work. I tried changing them to .so files, this did not work. It seems that windows is supposed to output a dll here, but the dll file did not work when attempting to import. It did not work as a dll file or a so file. I am not sure what to do here. Also, it seems that when these files are generated in every other tutorial or guide I see, there is a "lib" prefix on the name of each. I get no such prefix.
A dll file contains shared object code for COFF systems (like Windows) while a so file generally contains shared object code for ELF (and other) systems like Linux.
Renaming them will not work under any circumstance. If you have one and need the other, you need to rebuild them on the correct, matching, operating system.
I think you might be following instructions for Linux (due to the lib prefixes) on a Windows machine and then expecting some of the instructions to work. They might work, if you can identify all the "changes" between the platform and modify the Linux instructions to match the Windows platform; but until you know how to translate one environment's instructions to the other, it might be easier if you just find a set of Windows instructions that only refer to dll files and don't mention so files.

How to link gtk from Rust?

I'm using the GTK provided Rust example from https://www.gtk.org, and am wondering how to nail down GTK as a dependency (or other type of prerequisite) so that the Rust program given there will build with cargo.
Here's the code, copied from there without modification:
use gio::prelude::*;
use glib::clone;
use gtk::prelude::*;
// When the application is launched…
fn on_activate(application: &gtk::Application) {
// … create a new window …
let window = gtk::ApplicationWindow::new(application);
// … with a button in it …
let button = gtk::Button::new_with_label("Hello World!");
// … which closes the window when clicked
button.connect_clicked(clone!(#weak window => move |_| window.close()));
window.add(&button);
window.show_all();
}
fn main() {
// Create a new application
let app = gtk::Application::new(Some("com.github.gtk-rs.examples.basic"), Default::default())
.expect("Initialization failed...");
app.connect_activate(|app| on_activate(app));
// Run the application
app.run(&std::env::args().collect::<Vec<_>>());
}
As is, without any Cargo.toml definitions for gtk, gtk symbols will not resolve when compiling the program.
How would you go about it most idiomatically?
I do have GTK installed on my system of course.
Thanks!
Rust can call code using the C ABI, but as #Herohtar explains, it is not automatic. You need to give the compiler the information about the extern "C" functions to be able to call them.
For commonplace libraries, there may be existing bindings out there. These are Rust library crates that contain all the glue already written for you. They work like any other Rust dependency that you put in your Cargo.toml file.
So indeed I ended up following the suggested approach of using the gtk-rs rust integration project rather than pursue any gtk wrapper of my own. My initial source of confusion has been that the gtk website just gave the gtk-rs sample code without any reference or mention of the gtk-rs project being assumed.
The public crate which that code assumes, even though not explicitly stated in the original code sample page, is called gtk; I guess that's the default naming convention: that the namespace and crate name are typically the same.
Including that crate in the build indeed satisfies the gtk namespace appearing in the code. And the same trivial naming convention applies for the gio and glib namespace requirements appearing in the sample code. They all seem to come from the gtk-rs project, though unlike other programming languages, this is not explicitly evident in the crate specification as only the name of the create, not the project containing it, are specified in cargo.
As to versions, I have chosen the most recent version of the gtk crate (as per suggestion from my VSCode rust plugin) and the newest crate feature providing support for GTK's latest supported API.
And I have also arbitrarily plucked versions of the gio and glib crates off another gtk-rs project hoping for seamless interoperability between the last two and the gtk crate itself, as they seem to need to be separately specified and not brought in by the gtk crate itself.
So with the following dependency definitions in my Cargo.toml, the sample code works:
[dependencies]
gtk = { version = "0.9.2", features = ["v3_22"] }
glib = "0.10"
gio = { version = "0.9", features = ["v2_56"] }
I'm new to rust but I might at present time think some of this is more complicated than it could be or would be in the case of other rust projects, or, that using the sample code assumes familiarity with the compatibility scheme of gtk-rs crates or that of the underlying native compatibility of gtk with glib and gio versions!
The latter aspect might be simple enough but not explicitly discussed where gtk-rs documentation discusses versioning.
An odd sticking point for me was that the following method had to be replaced by me with the one following it, perhaps this code sample is just slightly outdated compared to the latest version of the crate (?!).
provided code sample:
gtk::Button::new_with_label
actual method that is defined:
gtk::Button::with_label

Qt 4.8.7 widget->move() not working on ARM linux

I have the following code:
QWidget* widget = ...
...
widget->move(x, y);
assert(widget->pos().x() == x);
assert(widget->pos().y() == y);
This assert holds on both Windows and Linux, but fails on embedded linux.
Qt was built from source on all operating systems.
Is there any known work around for this issue?

Resources