gtk-rs / gir Goto Github PK
View Code? Open in Web Editor NEWTool to generate rust bindings and user API for glib-based libraries
Home Page: https://gtk-rs.org/gir/book/
License: MIT License
Tool to generate rust bindings and user API for glib-based libraries
Home Page: https://gtk-rs.org/gir/book/
License: MIT License
I updated gir to last master branch update. When I run:
cargo run --release -- -c ../gtk/Gir.toml -d ../gir-files -o gtk
I get the following error:
"../gtk/Gir.toml": 452:6-452:6 error: expected a newline after table definition
Any idea?
PS: I also had to change the line 63 in src/statistics.rs
because Duration doesn't implement Display
trait (so I added .as_secs()
).
Part of #199
Some signals contains parameters from other modules:
CellArea: add-editable
CellRendererAccel: accel-edited
TextBuffer: insert-pixbuf
Widget: draw, screen-changed
Problem that current generator use codegen\sys\ffi_type.rs
for generate trampoline parameters,
so we get wrong module.
Ex.
fn connect_add_editable<F: Fn(&Self, &CellRenderer, &CellEditable, &cairo::RectangleInt, &str) + 'static>(&self, f: F) -> u64 {
unsafe {
let f: Box_<Box_<Fn(&Self, &CellRenderer, &CellEditable, &cairo::RectangleInt, &str) + 'static>> = Box_::new(Box_::new(f));
connect(self.to_glib_none().0, "add-editable",
transmute(add_editable_trampoline::<Self> as usize), Box_::into_raw(f) as *mut _)
}
}
unsafe extern "C" fn add_editable_trampoline<T>(this: *mut GtkCellArea, renderer: *mut GtkCellRenderer, editable: *mut GtkCellEditable, cell_area: *mut cairo::cairo_rectangle_int_t, path: *mut c_char, f: gpointer)
where T: IsA<CellArea> {
callback_guard!();
let f: &Box_<Fn(&T, &CellRenderer, &CellEditable, &cairo::RectangleInt, &str) + 'static> = transmute(f);
f(&CellArea::from_glib_none(this).downcast_unchecked(), &from_glib_none(renderer), &from_glib_none(editable), &from_glib_none(cell_area), &String::from_glib_none(path))
}
For add_editable_trampoline
must be cell_area: *mut cairo::cairo_ffi_rectangle_int_t
Also trampoline first parameter better be this: *mut ffi::GtkCellArea
(all ffi classes must be with module name)
If you still don't start it, i can begin do it (about 1 day) in following way:
Add in Gir.toml options.sys_subpath = "gtk-sys"
Generate funcs.rs with status = "generate"
widgets functions, that will be included and reexported in lib.rs.
All sys-depended code will go to sys
subdirs of analyze
and codegen
State of sys generation:
Features:
fontconfig
, freetype
, xlib
) need some solutionOption<fn(...)>
handling more precise to respect non-nullable paramerersDebug
for structs. This is complicated by the lack of impl Debug for fn(...)
Generator features:
gtk_dialog_get_content_area
gtk_container_get_path_for_child
Option<String>
gtk_container_forall
)gtk_container_get_children
)gtk_radio_action_get_group
)gtk_about_dialog_add_credit_section
, gtk_about_dialog_get_artists
)Some functions return bool
in addition to outparams with the understanding that returning FALSE
means the outparams haven't been initialized, this should translate to None
.
Example: gtk_widget_translate_coordinates
.
[[object]]
name = "Gtk.Entry"
status = "generate"
[[object.function]]
name = "set_placeholder_text"
[[object.function.parameter]]
name = "text"
nullable = true
Expected outcome:
fn set_placeholder_text(&self, text: Option<&str>);
Currently we're losing the outparam names.
This would need a way to track the presence of such structs and reexport in the parent modules. Also naming them could be difficult. Possibly control this manually?
When generating a struct
, it ends like this:
struct Foo {
fn a() {}
}
I'm working on fixing this.
For throwable function return value must return Result
(see discussion beginning at #117 (comment)).
2 types of throwable functions:
Result<(), glib::Error>
Blocked by #103
Part of #102
Seems records will more difficult that I think.
Object
but maybe without inheritance).gtk_sys
or separate some (with functions) or all.in
parameter then it passed by reference and translated with to_glib_none
.from_glib_none()
Possible preparation for #136.
Code chunks is objects that can convert yourself into code and forms treelike hierarchy.
For example Block
contains list of other chunks, Function definition
contains list of argument chunks and return value.
Distant goal: generate function definition
and ffi_function_definition
on analyze, do some transformation on them (ex. move output parameters to return values, group functions to Impl
or Trait
chunks).
On code generation phase generate function description (based on function definition
) and body chunks (based on function definition
and ffi_function_definition
) and write them to file.
Nearest goal: make function_body::Builder
generate body chunks and write them without change resulting code.
Tasks for nearest goal
name
, TypeId
e.t.c. for direct call.Next can be done realization throws and other out cases on chunks (#130, #144)
After this need check and remove formatters that can be replaced with use rustfmt
.
Problem both in Windows7 and Ubuntu.
On windows7 I don't have libsecret
installed, so don't worry about it.
But when I tried build on Ubuntu it still not generated with other error.
Running `/gir/target/release/gir -c gir-secret.toml`
thread '<main>' panicked at 'No such file or directory (os error 2) - ../gir-files/Secret-1.gir', /gir/src/parser.rs:37
Checked gir-files and don't found Secret-1.gir not in directory, not in git history.
Some function has outs and return something, they must return (ret, outs)
(Copy from #117 (comment))
gtk_cell_area_get_cell_at_position -> CellRenderer,
(throws)gtk_icon_info_load_symbolic -> GdkPixbuf.Pixbuf,
(throws)gtk_icon_info_load_symbolic_finish -> GdkPixbuf.Pixbuf,
(throws)gtk_icon_info_load_symbolic_for_context -> GdkPixbuf.Pixbuf,
(throws)gtk_icon_info_load_symbolic_for_context_finish -> GdkPixbuf.Pixbuf,
(throws, deprecated3.0)gtk_icon_info_load_symbolic_for_style -> GdkPixbuf.Pixbuf,
gtk_tree_selection_get_selected_rows -> GLib.List
All this functions return objects, so it can be converted by XXX::From_glib_none.
[options]
girs_dir = "gir-files"
library = "Gio"
version = "2.0"
min_cfg_version = "2.32"
target_path = "."
work_mode = "normal"
external_libraries = [
"GLib",
"GObject",
]
generate = [
"Gio.AppInfo",
"Gio.AppLaunchContext",
]
pub fn get_display<T: IsA<AppInfo>>(&self, info: &T, files: &[File]) -> Option<String> {
unsafe {
from_glib_full(ffi::g_app_launch_context_get_display(self.to_glib_none().0, info.to_glib_none().0, files.to_glib_none().0))
}
}
2 of these in gtk:
and one inout
:
IMHO it just stay manual for now.
I'm going to collect fun enum-related stories here.
int
s because that enum isn't exhaustive. GNOME/gtk@0b4af24. The native (i.e. not the FFI one) Rust enum has to account for that. Unfortunately the annotations are attached to function parameters of that type not to the type itself.Some signals have record parameters that used with RefMode::ByRefMut
(direct and boxed records),
so closure type looks like Fn(&CellRendererCombo, &str, &mut TreeIter) + 'static
but IMHO mutable really unneeded as it in
parameter.
Ex. CellArea: apply-attributes
CellRendererCombo: changed
EntryCompletion: cursor-on-match
Currently I hide mut
in codegen\trampoline::func_parameter
.
This is normal?
cc @gkoz
Part of #199
This
pub fn set_label_widget<T: Upcast<Widget>>(&self, label_widget: Option<&T>)
requires jumping through hoops to pass None
:
x.set_label_widget(None::<Widget>);
There's not much we can do to help it at the moment, because default type parameters don't inform type inference yet. When that is fixed the following signature is going to be more ergonomic;
pub fn set_label_widget<T: Upcast<Widget> = Widget>(&self, label_widget: Option<&T>)
Calling only the analyzers you need from codegen seems limiting and requires workarounds to avoid duplicate work.
A more robust scheme would be to do the analysis first and then let the codegen use that data. Expected benefits:
This is just a first approximation, I've not thought about the ways to organize the data. TypeId
would probably turn into DefId
. We could probably learn a thing or two from rustc
.
When I run gir from submodule
cargo run --release -- -c ..\Gir.toml
result generated files contains
// This file was generated by gir (???) from gir-files (???)
If I run from my main place, result generated files contains
// This file was generated by gir (503323c) from gir-files (???)
My git version 2.8.1
under msys2
Currently Config::new
returns Result<Config, ConfigError>
, but contains many panic!
and even exit
.
Tried to expand ConfigError cases to parsing options in https://github.com/EPashkin/gir/commits/error_case, but code look ugly as needed internal macros (which can be changed to new trait on Toml) and don't cover min_cfg_version
and starting Docopt
.
May be better just make Config::new
return Config
and panic on read_toml
result instead passing it to main
?
Part of #199
ListBox: row-selected
Widget: hierarchy-changed, parent-set
For closure Fn(&ListBox, Option<&ListBoxRow>) + 'static>
generated generated bad code.
Not sure if it need be fixed in gir
or in glib\gtk
.
unsafe extern "C" fn row_selected_trampoline(this: *mut GtkListBox, row: *mut GtkListBoxRow, f: gpointer) {
callback_guard!();
let f: &Box_<Fn(&ListBox, Option<&ListBoxRow>) + 'static> = transmute(f);
f(&from_glib_none(this), Option<ListBoxRow>::from_glib_none(row))
}
-To set the value of a child property, use `ContainerExt::child_set_property`,
+To set the value of a child property, use `Container::child_set_property`,
`ContainerExt::child_set` or `ContainerExt::child_set_valist`.
To obtain the value of a child property, use
-`ContainerExt::child_get_property`, `ContainerExt::child_get` or
+`Container::child_get_property`, `ContainerExt::child_get` or
Now types from other libs shows wrong way. As example gtk_scale_get_layout
uses Pango.Layout
, but currently shows as 'Layout'.
To temporary fix problem I start branch https://github.com/EPashkin/gir/tree/comment_types_from_other_libs, but faced the problem: library's Class don't know, what namespace it belong.
Can I add ns:u16 to almost all types?
Final solution for this issue must be using pango::Layout
string as type?
Also, can I delete row
library.namespace_mut(INTERNAL_NAMESPACE).name = INTERNAL_NAMESPACE_NAME.into();
and it current replacement as unnecessary?
It's confusing for a path taken from the config to change depending on the current working directory. The only way to ensure predictability seems to start from the directory which contains the config.
The best modules organization is not entirely clear now. Possibly add modules bitfileds
, enums
, consts
under auto
.
Initially this is just a bunch of reexports like this:
pub use ffi::GtkAccelFlags as AccelFlags;
If #123 is decided in favor of converting enums, the enums
module will contain the enums definitions and conversion impls.
Part of #199
TreeView's: row-activated, row-collapsed, row-expanded, test-expand-row, test-collapse-row
CellArea: apply_attributes,
CellRendered: changed
in manual code use from_glib_borrow
for TreePath
, TreeIter
, .. in trampolines,
current code use from_glib_none
.
What better?
May be it linked with #240
cc @gkoz
All* non-method functions functions need to have safety assertions introduced in gtk-rs/gtk#189, e.g.
impl Box {
pub fn new(orientation: Orientation, spacing: i32) -> Box {
assert_initialized_main_thread!();
...
* if we take an object that has an assertion in its constructor, it can be skipped, but this optimization is not strictly necessary:
impl Layout {
pub fn new(hadjustment: &Adjustment, vadjustment: &Adjustment) -> Layout {
skip_assert_initialized!();
...
The whole feature should probably be optional.
For now, here is the list of things we need to update inside the parsed documentation:
C // some code
".%s
" (example "@accel_mods" into "accel_mods
").The following one will be done later:
In gtk currently we have next dirs for classes: dialog, widgets, window.
For automatic detect dirs propose add path to object
in gir.toml and select path for nearest parent with path.
[[object]]
name = "Gtk.Widget"
path = "widgets"
[[object]]
name = "Gtk.Window"
path = "window" # or "windows"
[[object]]
name = "Gtk.Dialog"
path = "dialog" # "dialogs"
This can be expanded to interfaces (but needed list all choosers as its has no common parent).
Maybe it unnecessary or has better solution.
Part of #102.
Found that returning arrays and lists can be created with FromGlibPtrContainer
.
But not sure what use for converting parameters. IterToGlibPtr
?
It might be a good idea to test if the enums we get from the other side have valid values. This could require using newtype c_int
wrappers instead of enums in the sys layer and implementing conversions between that and Rust enums.
Currently we have too many issues, but mostly its not really necessary for main task (replace current gtk-rs
paradigm).
Not better focus to add working example like basic.rs
to prove that concept is really works?
For this needed only functions from rt.rs
and some basic signals (really needed only connect_delete_event
that can be added to already manual window\mod.rs
)
As a first step, copy the documentation from the GIRs altering the formatting to make rustdoc happy (change %FOO
or @FOO
, etc. to FOO
). Apply more processing to taste.
The next goal is having a toml
or something with hand-written docs overrides.
IMHO we need a module for testing codegen/function.rs functions declaration
and body
for some cases.
I not sure where to place this module: in function.rs
or in tests directory.
Sample tests:
#[test]
fn decl_gtk_switch_set_active () {
assert_eq!(code_func_decl("Gtk.Switch", "set_active"), "fn set_active(&self, is_active: bool)");
}
#[test]
fn body_gtk_switch_set_active () {
assert_eq!(code_func_body("Gtk.Switch", "set_active"), "unsafe { ffi::gtk_switch_set_active(self.to_glib_none().0, is_active.to_glib()); }");
}
code_func_xxx
is helper functions(macros) that get Libray
, analyses function and call codegen::function::xxx
.
It would be better if all tests use same copy of Library
.
Which better set of names for types in constraint: T, U, V, W, X,Y,Z or T, T2, T3,... ?
Currently out parameters treated same way that result code like this
fn query_child_packing<T: Upcast<Widget>>(&self, child: &T) -> (bool, bool, u32, PackType) {
let mut expand.to_glib() = Default::default();
let mut fill.to_glib() = Default::default();
let mut padding = Default::default();
let mut pack_type = Default::default();
unsafe {
ffi::gtk_box_query_child_packing(self.upcast().to_glib_none().0, child.upcast().to_glib_none().0, &mut expand.to_glib(), &mut fill.to_glib(), &mut padding, &mut pack_type);
}
(expand.to_glib(), fill.to_glib(), padding, pack_type)
}
List of ffi functions which must return out parameters
gtk_paper_size_is_ipp
seems to be missing a version="3.16"
annotation. We might either want to support version overrides or just handle this manually.
For adding posibility parameters type rewrite I proposed changes in analysis::functions::Info
:
Vec<library::Parameter>
ParameterDirection::return
error
parameter to rust's list (may be with ParameterDirection::error
)Vec<Transformation>
, wherestruct Transformation {
ind_c: i32, //index in `Vec<library::Parameter>`
ind_rust: i32, //index in 'Vec<analysis::parameter::Parameter>`
conversion: ConversionType, //Used in ffi-function call parameters and return converting
pre_transformation: PreTransformationType,
post_transformation: PostTransformationType,
}
enum PreTransformationType {
None,
VarUninitialized, //for string like "let mut padding_top = mem::uninitialized();" in function body
VarUnititializedType, //for "let mut aligned_area = gdk::Rectangle::uninitialized();"
VarNullPointer, //for "let mut path = ptr::null_mut();"
VarError, //for "let mut error = ptr::null_mut();"
}
enum PostTransformationType {
None,
Return, //for adding to return Tuple
ReturnOption, //on original return parameter for returning Option<(...)>
ReturnError, //"if error.is_null() { Ok(()) } else { Err(from_glib_full(error)) }"
}
In future we can add transformation for write one name: String
parameter to 2 ffi parameters: ptr and size, etc.
Same change can be applied to trampolines, and may be it even bigger priority, as they needed from_glib_borrow
replacement, string conversion (editable::insert_trampoline
), gtk_tree_path_new_from_string
conversion etc.
gtk_text_iter_attributes looks like it doesn't just overwrite values
but modifies it. It should probably be inout
yet we get
<parameter name="values"
direction="out"
caller-allocates="1"
transfer-ownership="none">
<doc xml:space="preserve">a #GtkTextAttributes to be filled in</doc>
<type name="TextAttributes" c:type="GtkTextAttributes*"/>
</parameter>
This isn't particularly high priority as TextAttributes
seem pretty obscure.
Upgrade the "upcasts" feature to support taking Fundamental::Filename
as
fn select_filename<T: AsRef<Path>>(&self, filename: T) -> bool
Some types (GtkCheckButton
) have children and only constructors (no trait).
So for it's children ('GtkRadioButton') we better skip parent upcast.
We can just add empty trait or go hard way.
Currently seen only GtkCheckButton
, so empty trait IMHO will do.
Inhibit
not bool
.RangeExt::change-value
gkoz: It appears a significant number of signals need Inhibit, with varying degrees of certainty:
EntryCompletion
Label::activate-link
(?)LinkButton::activate-link
MenuShell::move-selected
Notebook::change-current-page
and others (??)Paned
(?)SpinButton::output
(?)StatusIcon::size-changed
Switch::state-set
ToolItem::create-menu-proxy
Toolbar
Signals with Inhibit
detected by _gtk_boolean_handled_accumulator
in gtk
sources
AboutDialog
: activate-link
AccelGroup
: accel-activate (not meant to be used by applications)
EntryCompletion
insert-prefix
match-selected
cursor-on-match
GLArea
: render (already manual with Inhibit)
IMContext
retrieve-surrounding
delete-surrounding
Label
: activate-link
LinkButton
: activate-link
MenuShell
: move-selected
Overlay
: get-child-position (output)
PrintOperation
paginate (?)
preview
Range
: change-value (already manual with Inhibit)
Socket
: plug-removed
SpinButton
: output (already manual with Inhibit)
Switch
: state-set
TextTag
: event
TextView
: extend-selection
Toolbar
: popup-context-menu
ToolItem
: create-menu-proxy
TreeView
all already manual but not Inhibit
test-expand-row
test-collapse-row
Widget
(+ already manual with Inhibit, - not added, some added but return bool
)
draw +
mnemonic-activate +
focus +
keynav-failed +
event +
button-press-event +
button-release-event +
touch-event + (?)
scroll-event +
motion-notify-event +
delete-event +
destroy-event +
key-press-event +
key-release-event +
enter-notify-event +
leave-notify-event +
configure-event +
focus-in-event +
focus-out-event +
map-event +
unmap-event +
property-notify-event +
selection-clear-event - (+)
selection-request-event - (+)
selection-notify-event - (+)
proximity-in-event +
proximity-out-event +
drag-failed - (+)
drag-motion - (-)
drag-drop - (-)
visibility-notify-event - (+)
window-state-event +
damage-event +
grab-broken-event +
query-tooltip currently not Inhibit
popup-menu currently not Inhibit
show-help currently not Inhibit (+)
can-activate-accel currently not Inhibit
UPDATE: Issue fixed but in temporary way.
Not all Inhibit functions generated.
CellRendererCombo::changed
and others accept tree path string, that better be converted to TreePath
in closure.
It can be configured as parameter options.
Example of trampoline:
unsafe extern "C" fn trampoline(this: *mut GtkCellRendererCombo,
path: *const c_char,
new_iter: *mut GtkTreeIter,
f: &Box<Fn(&CellRendererCombo, TreePath, &TreeIter) + 'static>) {
callback_guard!();
let path = from_glib_full(gtk_tree_path_new_from_string(path));
f(&CellRendererCombo::from_glib_none(this), path, &from_glib_borrow(new_iter));
}
Generate pub trait xxxSignals
for classes with "IsA" implementation for classes with children
or direct implimentation for classes without children (same as for "xxxExt" traits).
For both cases generate trampoline function.
Example for ComboBox and TreeSelection: https://github.com/EPashkin/rust-gnome-gtk/tree/signal_sample
The doc generator should enumerate the variant consts in the bitfield type documentation because they're hard to find otherwise.
For instance, gtk_widget_activate
vs gtk_menu_item_activate
.
Emit a warning -- in cases I've seen so far they're essentially duplicate, but who knows.
Bonus points for comparing the signatures.
In gtk some callback return utf8
(gchar*
), current trampolines format don't support it.
Found two of these:
GtkComboBox
: format-entry-text
GtkScale
: format-value
May be problem with other pointer returning signals.
It is necessary to generate a lines with "use xxx;".
I believe that it is better to add some mutable state to avoid duplication.
Not sure it will be added to env::Env
via RefCell
or to separate struct.
Now I see the following sources of necessary types:
glib::translate: *, glib::types, ffi
object::{Object, Upcast}
with DownCast
when constructors presentimpl_parents
impl_interfaces
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.