Skip to content

Commit c0a950b

Browse files
committed
fix example and add tk crate
1 parent 1c688a4 commit c0a950b

File tree

13 files changed

+241
-25
lines changed

13 files changed

+241
-25
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[workspace]
22
members = [
3-
"shared-build", "tcl", "tcl-sys", "tk-sys"
3+
"shared-build", "tcl", "tcl-sys", "tk", "tk-sys"
44
]
55
resolver = "3"
66

shared-build/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,9 @@ pub fn build(
5454
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
5555
.blocklist_function("Tcl_DecrRefCount")
5656
.blocklist_function("Tcl_IncrRefCount");
57+
5758
if tk {
58-
builder = builder.blocklist_item("Tcl_.*");
59+
builder = builder.blocklist_item("(Tcl|TCL).*");
5960
}
6061
for dir in get_include_dirs() {
6162
builder = builder.clang_arg(format!("-I{dir}"));

tcl/Cargo.toml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
[package]
22
name = "tcl"
3-
edition.workspace = true
3+
44
authors.workspace = true
5+
edition.workspace = true
6+
include.workspace = true
7+
license.workspace = true
58
readme.workspace = true
69
repository.workspace = true
7-
version.workspace = true
8-
license.workspace = true
9-
include.workspace = true
1010
rust-version.workspace = true
11+
version.workspace = true
12+
13+
description = "TCL bindings for Rust"
1114

1215
[dependencies]
1316
tcl-sys = { version = "0.3", path = "../tcl-sys" }

tcl/src/interp.rs

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,16 @@ impl Interp {
1515
Interp(NonNull::new(interp).unwrap())
1616
}
1717

18+
pub unsafe fn as_ptr(&self) -> *mut tcl_sys::Tcl_Interp {
19+
self.0.as_ptr()
20+
}
21+
22+
pub fn init(&mut self) -> i32 {
23+
unsafe {
24+
tcl_sys::Tcl_Init(self.0.as_ptr()) as i32
25+
}
26+
}
27+
1828
pub fn create_slave(&mut self, name: &str, is_safe: i32) -> Self {
1929
let name = std::ffi::CString::new(name).unwrap();
2030
let interp = unsafe {
@@ -36,26 +46,44 @@ impl Interp {
3646
}
3747

3848
pub unsafe fn get_obj_result(&self) -> Obj {
39-
Obj::from_raw(tcl_sys::Tcl_GetObjResult(self.0.as_ptr()))
49+
unsafe {
50+
Obj::from_raw(tcl_sys::Tcl_GetObjResult(self.0.as_ptr()))
51+
}
52+
}
53+
54+
pub unsafe fn get_string_result(&self) -> String {
55+
let result = self.get_obj_result();
56+
let result_ptr = tcl_sys::Tcl_GetString(result.0.as_ptr());
57+
let _ = tcl_sys::Tcl_GetStringResult(self.0.as_ptr());
58+
let result_str = std::ffi::CStr::from_ptr(result_ptr);
59+
result_str.to_string_lossy().into_owned()
4060
}
4161

4262
pub unsafe fn eval(&self, script: &str) -> i32 {
4363
let script = std::ffi::CString::new(script).unwrap();
44-
tcl_sys::Tcl_Eval(self.0.as_ptr(), script.as_ptr()) as i32
64+
unsafe {
65+
tcl_sys::Tcl_Eval(self.0.as_ptr(), script.as_ptr()) as i32
66+
}
4567
}
4668

4769
pub unsafe fn eval_ex(&self, script: &str, num_bytes: i32, flags: i32) -> i32 {
4870
let script = std::ffi::CString::new(script).unwrap();
49-
tcl_sys::Tcl_EvalEx(self.0.as_ptr(), script.as_ptr(), num_bytes, flags) as i32
71+
unsafe {
72+
tcl_sys::Tcl_EvalEx(self.0.as_ptr(), script.as_ptr(), num_bytes, flags) as i32
73+
}
5074
}
5175

5276
pub unsafe fn eval_obj(&self, obj: Obj) -> i32 {
53-
tcl_sys::Tcl_EvalObj(self.0.as_ptr(), obj.0.as_ptr()) as i32
77+
unsafe {
78+
tcl_sys::Tcl_EvalObj(self.0.as_ptr(), obj.0.as_ptr()) as i32
79+
}
5480
}
5581

5682
pub unsafe fn eval_file(&self, filename: &str) -> i32 {
5783
let filename = std::ffi::CString::new(filename).unwrap();
58-
tcl_sys::Tcl_EvalFile(self.0.as_ptr(), filename.as_ptr()) as i32
84+
unsafe {
85+
tcl_sys::Tcl_EvalFile(self.0.as_ptr(), filename.as_ptr()) as i32
86+
}
5987
}
6088
}
6189

tcl/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ pub use interp::Interp;
66
pub use obj::Obj;
77
pub use time::Time;
88

9+
pub use tcl_sys as raw;
10+
pub use tcl_sys::TCL_ERROR;
11+
912
pub fn get_errno() -> i32 {
1013
unsafe {
1114
tcl_sys::Tcl_GetErrno() as _

tcl/src/obj.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ impl Obj {
1414
Obj(NonNull::new(obj).expect("Failed to create Tcl_Obj from raw pointer"))
1515
}
1616

17+
18+
pub unsafe fn as_ptr(&self) -> *mut tcl_sys::Tcl_Obj {
19+
self.0.as_ptr()
20+
}
21+
1722
pub fn from_string(string: &str) -> Self {
1823
let c_str = std::ffi::CString::new(string).expect("Failed to create CString");
1924
let obj = unsafe { tcl_sys::Tcl_NewStringObj(c_str.as_ptr(), c_str.as_bytes().len() as i32) };
@@ -91,10 +96,10 @@ impl Obj {
9196
}
9297

9398
pub fn get_long(&self) -> Option<i64> {
94-
let mut value: i64 = 0;
95-
let result = unsafe { tcl_sys::Tcl_GetLongFromObj(std::ptr::null_mut(), self.0.as_ptr(), value as _) };
99+
let mut value = 0 as _;
100+
let result = unsafe { tcl_sys::Tcl_GetLongFromObj(std::ptr::null_mut(), self.0.as_ptr(), &mut value) };
96101
if result == 0 {
97-
Some(value)
102+
Some(value as _)
98103
} else {
99104
None
100105
}

tk-sys/examples/simple.rs

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,48 @@
1+
use std::ffi::CStr;
2+
use std::process::exit;
3+
use tk_sys::*;
4+
use tcl_sys::*;
5+
16
fn main() {
27
unsafe {
3-
let interp = tcl_sys::Tcl_CreateInterp();
4-
tk_sys::Tk_Init(interp);
5-
let window = tk_sys::Tk_MainWindow(interp);
6-
tk_sys::Tk_SetAppName(window, b"simple\0".as_ptr() as _);
7-
tcl_sys::Tcl_Eval(interp, b"button .b -text \"Click Me\" -command {puts \"Hello from Tk\"}\0".as_ptr() as _);
8-
tcl_sys::Tcl_Eval(interp, b"pack .b\0".as_ptr() as _);
9-
10-
// Start the main event loop
11-
tk_sys::Tk_MainLoop();
8+
// Create a new Tcl interpreter
9+
let interp = Tcl_CreateInterp();
10+
11+
// Initialize Tcl
12+
if Tcl_Init(interp) == TCL_ERROR as i32 {
13+
let err = CStr::from_ptr(Tcl_GetStringResult(interp));
14+
eprintln!("Tcl_Init error: {}", err.to_string_lossy());
15+
exit(1);
16+
}
17+
18+
// Initialize Tk
19+
if Tk_Init(interp) == TCL_ERROR as i32 {
20+
let err = CStr::from_ptr(Tcl_GetStringResult(interp));
21+
eprintln!("Tk_Init error: {}", err.to_string_lossy());
22+
exit(1);
23+
}
24+
25+
// Create the main application window
26+
let main_window = Tk_MainWindow(interp);
27+
if main_window.is_null() {
28+
let err = CStr::from_ptr(Tcl_GetStringResult(interp));
29+
eprintln!("Failed to create main window: {}", err.to_string_lossy());
30+
exit(1);
31+
}
32+
33+
// Set the application name
34+
let app_name = b"SimpleTkApp\0".as_ptr() as *const i8;
35+
Tk_SetAppName(main_window, app_name);
36+
37+
// Create a button widget via Tcl scripting
38+
let create_btn = b"button .b -text \"Click Me\" -command {puts \"Hello from Tk\"}\0".as_ptr() as *const i8;
39+
Tcl_Eval(interp, create_btn);
40+
41+
// Pack the button into the window
42+
let pack_btn = b"pack .b\0".as_ptr() as *const i8;
43+
Tcl_Eval(interp, pack_btn);
44+
45+
// Enter the Tk event loop
46+
Tk_MainLoop();
1247
}
13-
}
48+
}

tk-sys/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,3 @@
55
use tcl_sys::*;
66

77
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
8-
include!(concat!(env!("OUT_DIR"), "/custom.rs"));

tk/Cargo.toml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[package]
2+
name = "tk"
3+
4+
authors.workspace = true
5+
edition.workspace = true
6+
include.workspace = true
7+
license.workspace = true
8+
readme.workspace = true
9+
repository.workspace = true
10+
rust-version.workspace = true
11+
version.workspace = true
12+
13+
description = "TK bindings for Rust"
14+
15+
[dependencies]
16+
tcl = { version = "0.3", path = "../tcl" }
17+
tk-sys = { version = "0.3", path = "../tk-sys" }

tk/examples/simple.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
use std::process::exit;
2+
use tcl::*;
3+
use tk::InterpExt;
4+
5+
fn main() {
6+
unsafe {
7+
// Create a new Tcl interpreter
8+
let mut interp = Interp::new();
9+
10+
// Initialize Tcl
11+
if interp.init() == TCL_ERROR as i32 {
12+
let err = interp.get_string_result();
13+
eprintln!("Tcl_Init error: {}", err);
14+
exit(1);
15+
}
16+
17+
// Initialize Tk
18+
if interp.tk_init() == TCL_ERROR as i32 {
19+
let err = interp.get_string_result();
20+
eprintln!("Tk_Init error: {}", err);
21+
exit(1);
22+
}
23+
24+
// Create the main application window
25+
let mut main_window = tk::Window::main_window(&interp);
26+
if main_window.is_none() {
27+
let err = interp.get_string_result();
28+
eprintln!("Failed to create main window: {}", err);
29+
exit(1);
30+
}
31+
let mut main_window = main_window.unwrap();
32+
33+
// Set the application name
34+
main_window.set_app_name("SimpleTkApp");
35+
36+
// Create a button widget via Tcl scripting
37+
interp.eval("button .b -text \"Click Me\" -command {puts \"Hello from Tk\"}");
38+
39+
// Pack the button into the window
40+
interp.eval("pack .b");
41+
42+
// Enter the Tk event loop
43+
tk::main_loop();
44+
}
45+
}

0 commit comments

Comments
 (0)