mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 10:44:36 +08:00
_tkinter pt. 2 (#5640)
This commit is contained in:
1 parent
98137eb79c
commit
be56911598
6 files changed
+746
-546
No files matched your search
@@ -224,6 +224,7 @@ sysvars
|
||||
teedata
|
||||
thisclass
|
||||
titlecased
|
||||
tkapp
|
||||
tobytes
|
||||
tolist
|
||||
toreadonly
|
||||
|
||||
Generated
+296
-495
File diff suppressed because it is too large.
Load diff
Vendored
+3
-1
@@ -2451,7 +2451,9 @@ class Tk(Misc, Wm):
|
||||
self.tk = None
|
||||
if baseName is None:
|
||||
import os
|
||||
baseName = os.path.basename(sys.argv[0])
|
||||
# TODO: RUSTPYTHON
|
||||
# baseName = os.path.basename(sys.argv[0])
|
||||
baseName = "" # sys.argv[0]
|
||||
baseName, ext = os.path.splitext(baseName)
|
||||
if ext not in ('.py', '.pyc'):
|
||||
baseName = baseName + ext
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg version="1.1" width="1200" height="60" onload="init(evt)" viewBox="0 0 1200 60" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:fg="http://github.com/jonhoo/inferno"><!--Flame graph stack visualization. See https://github.com/brendangregg/FlameGraph for latest version, and http://www.brendangregg.com/flamegraphs.html for examples.--><!--NOTES: --><text x="50.0000%" y="24.00">ERROR: No valid input provided to flamegraph</text></svg>
|
||||
|
After Width: | Height: | Size: 611 B |
+3
-3
@@ -18,7 +18,7 @@ bz2 = ["bzip2"]
|
||||
sqlite = ["dep:libsqlite3-sys"]
|
||||
ssl = ["openssl", "openssl-sys", "foreign-types-shared", "openssl-probe"]
|
||||
ssl-vendor = ["ssl", "openssl/vendored"]
|
||||
tkinter = ["dep:tk", "dep:tcl"]
|
||||
tkinter = ["dep:tk-sys", "dep:tcl-sys"]
|
||||
|
||||
[dependencies]
|
||||
# rustpython crates
|
||||
@@ -83,8 +83,8 @@ libz-sys = { package = "libz-rs-sys", version = "0.4" }
|
||||
bzip2 = { version = "0.4", optional = true }
|
||||
|
||||
# tkinter
|
||||
tk = { version = "0.1.10", optional = true }
|
||||
tcl = { version = "0.1.9", optional = true }
|
||||
tk-sys = { git = "https://github.com/arihant2math/tkinter.git", tag = "v0.1.0", optional = true }
|
||||
tcl-sys = { git = "https://github.com/arihant2math/tkinter.git", tag = "v0.1.0", optional = true }
|
||||
|
||||
# uuid
|
||||
[target.'cfg(not(any(target_os = "ios", target_os = "android", target_os = "windows", target_arch = "wasm32", target_os = "redox")))'.dependencies]
|
||||
|
||||
+442
-47
@@ -4,83 +4,478 @@ pub(crate) use self::_tkinter::make_module;
|
||||
|
||||
#[pymodule]
|
||||
mod _tkinter {
|
||||
use rustpython_vm::types::Constructor;
|
||||
use rustpython_vm::{PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine};
|
||||
|
||||
use rustpython_vm::builtins::{PyInt, PyStr, PyType};
|
||||
use std::{ffi, ptr};
|
||||
|
||||
use crate::builtins::PyTypeRef;
|
||||
use rustpython_vm::function::{Either, FuncArgs};
|
||||
use rustpython_vm::{PyResult, VirtualMachine, function::OptionalArg};
|
||||
use rustpython_common::atomic::AtomicBool;
|
||||
use rustpython_common::atomic::Ordering;
|
||||
|
||||
use crate::common::lock::PyRwLock;
|
||||
use std::sync::Arc;
|
||||
use tk::cmd::*;
|
||||
use tk::*;
|
||||
|
||||
#[pyattr]
|
||||
const TK_VERSION: &str = "8.6";
|
||||
#[pyattr]
|
||||
const TCL_VERSION: &str = "8.6";
|
||||
#[pyattr]
|
||||
const READABLE: i32 = 2;
|
||||
#[pyattr]
|
||||
const WRITABLE: i32 = 4;
|
||||
#[pyattr]
|
||||
const EXCEPTION: i32 = 8;
|
||||
|
||||
fn demo() -> tk::TkResult<()> {
|
||||
let tk = make_tk!()?;
|
||||
let root = tk.root();
|
||||
root.add_label(-text("constructs widgets and layout step by step"))?
|
||||
.pack(())?;
|
||||
let f = root.add_frame(())?.pack(())?;
|
||||
let _btn = f
|
||||
.add_button("btn" - text("quit") - command("destroy ."))?
|
||||
.pack(())?;
|
||||
Ok(main_loop())
|
||||
#[cfg(windows)]
|
||||
fn _get_tcl_lib_path() -> String {
|
||||
// TODO: fix packaging
|
||||
String::from(r"C:\ActiveTcl\lib")
|
||||
}
|
||||
|
||||
#[pyattr(once, name = "TclError")]
|
||||
#[pyattr(name = "TclError", once)]
|
||||
fn tcl_error(vm: &VirtualMachine) -> PyTypeRef {
|
||||
vm.ctx.new_exception_type(
|
||||
"zlib",
|
||||
"_tkinter",
|
||||
"TclError",
|
||||
Some(vec![vm.ctx.exceptions.exception_type.to_owned()]),
|
||||
)
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn create(args: FuncArgs, _vm: &VirtualMachine) -> PyResult<TkApp> {
|
||||
// TODO: handle arguments
|
||||
// TODO: this means creating 2 tk instances is not possible.
|
||||
let tk = Tk::new(()).unwrap();
|
||||
Ok(TkApp {
|
||||
tk: Arc::new(PyRwLock::new(tk)),
|
||||
})
|
||||
#[pyattr(name = "TkError", once)]
|
||||
fn tk_error(vm: &VirtualMachine) -> PyTypeRef {
|
||||
vm.ctx.new_exception_type(
|
||||
"_tkinter",
|
||||
"TkError",
|
||||
Some(vec![vm.ctx.exceptions.exception_type.to_owned()]),
|
||||
)
|
||||
}
|
||||
|
||||
#[pyattr(once, name = "TK_VERSION")]
|
||||
fn tk_version(_vm: &VirtualMachine) -> String {
|
||||
format!("{}.{}", 8, 6)
|
||||
}
|
||||
|
||||
#[pyattr(once, name = "TCL_VERSION")]
|
||||
fn tcl_version(_vm: &VirtualMachine) -> String {
|
||||
format!(
|
||||
"{}.{}",
|
||||
tk_sys::TCL_MAJOR_VERSION,
|
||||
tk_sys::TCL_MINOR_VERSION
|
||||
)
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "TclObject")]
|
||||
#[derive(PyPayload)]
|
||||
struct TclObject {
|
||||
value: *mut tk_sys::Tcl_Obj,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for TclObject {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "TclObject")
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Send for TclObject {}
|
||||
unsafe impl Sync for TclObject {}
|
||||
|
||||
#[pyclass]
|
||||
impl TclObject {}
|
||||
|
||||
static QUIT_MAIN_LOOP: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "tkapp")]
|
||||
#[derive(PyPayload)]
|
||||
struct TkApp {
|
||||
tk: Arc<PyRwLock<tk::Tk<()>>>,
|
||||
// Tcl_Interp *interp;
|
||||
interpreter: *mut tk_sys::Tcl_Interp,
|
||||
// int wantobjects;
|
||||
want_objects: bool,
|
||||
// int threaded; /* True if tcl_platform[threaded] */
|
||||
threaded: bool,
|
||||
// Tcl_ThreadId thread_id;
|
||||
thread_id: Option<tk_sys::Tcl_ThreadId>,
|
||||
// int dispatching;
|
||||
dispatching: bool,
|
||||
// PyObject *trace;
|
||||
trace: Option<()>,
|
||||
// /* We cannot include tclInt.h, as this is internal.
|
||||
// So we cache interesting types here. */
|
||||
old_boolean_type: *const tk_sys::Tcl_ObjType,
|
||||
boolean_type: *const tk_sys::Tcl_ObjType,
|
||||
byte_array_type: *const tk_sys::Tcl_ObjType,
|
||||
double_type: *const tk_sys::Tcl_ObjType,
|
||||
int_type: *const tk_sys::Tcl_ObjType,
|
||||
wide_int_type: *const tk_sys::Tcl_ObjType,
|
||||
bignum_type: *const tk_sys::Tcl_ObjType,
|
||||
list_type: *const tk_sys::Tcl_ObjType,
|
||||
string_type: *const tk_sys::Tcl_ObjType,
|
||||
utf32_string_type: *const tk_sys::Tcl_ObjType,
|
||||
pixel_type: *const tk_sys::Tcl_ObjType,
|
||||
}
|
||||
|
||||
unsafe impl Send for TkApp {}
|
||||
|
||||
unsafe impl Sync for TkApp {}
|
||||
|
||||
impl std::fmt::Debug for TkApp {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("TkApp").finish()
|
||||
write!(f, "TkApp")
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
#[derive(FromArgs, Debug)]
|
||||
struct TkAppConstructorArgs {
|
||||
#[pyarg(any)]
|
||||
screen_name: Option<String>,
|
||||
#[pyarg(any)]
|
||||
_base_name: Option<String>,
|
||||
#[pyarg(any)]
|
||||
class_name: String,
|
||||
#[pyarg(any)]
|
||||
interactive: i32,
|
||||
#[pyarg(any)]
|
||||
wantobjects: i32,
|
||||
#[pyarg(any, default = "true")]
|
||||
want_tk: bool,
|
||||
#[pyarg(any)]
|
||||
sync: i32,
|
||||
#[pyarg(any)]
|
||||
use_: Option<String>,
|
||||
}
|
||||
|
||||
impl Constructor for TkApp {
|
||||
type Args = TkAppConstructorArgs;
|
||||
|
||||
fn py_new(
|
||||
_zelf: PyRef<PyType>,
|
||||
args: Self::Args,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyObjectRef> {
|
||||
create(args, vm)
|
||||
}
|
||||
}
|
||||
|
||||
fn varname_converter(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<String> {
|
||||
// if let Ok(bytes) = obj.bytes(vm) {
|
||||
// todo!()
|
||||
// }
|
||||
|
||||
// str
|
||||
if let Some(str) = obj.downcast_ref::<PyStr>() {
|
||||
return Ok(str.as_str().to_string());
|
||||
}
|
||||
|
||||
if let Some(_tcl_obj) = obj.downcast_ref::<TclObject>() {
|
||||
// Assume that the Tcl object has a method to retrieve a string.
|
||||
// return tcl_obj.
|
||||
todo!();
|
||||
}
|
||||
|
||||
// Construct an error message using the type name (truncated to 50 characters).
|
||||
Err(vm.new_type_error(format!(
|
||||
"must be str, bytes or Tcl_Obj, not {:.50}",
|
||||
obj.obj_type().str(vm)?.as_str()
|
||||
)))
|
||||
}
|
||||
|
||||
// TODO: DISALLOW_INSTANTIATION
|
||||
#[pyclass(with(Constructor))]
|
||||
impl TkApp {
|
||||
#[pymethod]
|
||||
fn getvar(&self, name: &str) -> PyResult<String> {
|
||||
let tk = self.tk.read().unwrap();
|
||||
Ok(tk.getvar(name).unwrap())
|
||||
fn from_bool(&self, obj: *mut tk_sys::Tcl_Obj) -> bool {
|
||||
let mut res = -1;
|
||||
unsafe {
|
||||
if tk_sys::Tcl_GetBooleanFromObj(self.interpreter, obj, &mut res)
|
||||
!= tk_sys::TCL_OK as i32
|
||||
{
|
||||
panic!("Tcl_GetBooleanFromObj failed");
|
||||
}
|
||||
}
|
||||
assert!(res == 0 || res == 1);
|
||||
res != 0
|
||||
}
|
||||
|
||||
fn from_object(
|
||||
&self,
|
||||
obj: *mut tk_sys::Tcl_Obj,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyObjectRef> {
|
||||
let type_ptr = unsafe { (*obj).typePtr };
|
||||
if type_ptr == ptr::null() {
|
||||
return self.unicode_from_object(obj, vm);
|
||||
} else if type_ptr == self.old_boolean_type || type_ptr == self.boolean_type {
|
||||
return Ok(vm.ctx.new_bool(self.from_bool(obj)).into());
|
||||
} else if type_ptr == self.string_type
|
||||
|| type_ptr == self.utf32_string_type
|
||||
|| type_ptr == self.pixel_type
|
||||
{
|
||||
return self.unicode_from_object(obj, vm);
|
||||
}
|
||||
// TODO: handle other types
|
||||
|
||||
return Ok(TclObject { value: obj }.into_pyobject(vm));
|
||||
}
|
||||
|
||||
fn unicode_from_string(
|
||||
s: *mut ffi::c_char,
|
||||
size: usize,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyObjectRef> {
|
||||
// terribly unsafe
|
||||
let s = unsafe { std::slice::from_raw_parts(s, size) }
|
||||
.to_vec()
|
||||
.into_iter()
|
||||
.map(|c| c as u8)
|
||||
.collect::<Vec<u8>>();
|
||||
let s = String::from_utf8(s).unwrap();
|
||||
Ok(PyObjectRef::from(vm.ctx.new_str(s)))
|
||||
}
|
||||
|
||||
fn unicode_from_object(
|
||||
&self,
|
||||
obj: *mut tk_sys::Tcl_Obj,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyObjectRef> {
|
||||
let type_ptr = unsafe { (*obj).typePtr };
|
||||
if type_ptr != ptr::null()
|
||||
&& self.interpreter != ptr::null_mut()
|
||||
&& (type_ptr == self.string_type || type_ptr == self.utf32_string_type)
|
||||
{
|
||||
let len = ptr::null_mut();
|
||||
let data = unsafe { tk_sys::Tcl_GetUnicodeFromObj(obj, len) };
|
||||
return if size_of::<tk_sys::Tcl_UniChar>() == 2 {
|
||||
let v = unsafe { std::slice::from_raw_parts(data as *const u16, len as usize) };
|
||||
let s = String::from_utf16(v).unwrap();
|
||||
Ok(PyObjectRef::from(vm.ctx.new_str(s)))
|
||||
} else {
|
||||
let v = unsafe { std::slice::from_raw_parts(data as *const u32, len as usize) };
|
||||
let s = widestring::U32String::from_vec(v).to_string_lossy();
|
||||
Ok(PyObjectRef::from(vm.ctx.new_str(s)))
|
||||
};
|
||||
}
|
||||
let len = ptr::null_mut();
|
||||
let s = unsafe { tk_sys::Tcl_GetStringFromObj(obj, len) };
|
||||
Self::unicode_from_string(s, len as _, vm)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn createcommand(&self, name: String, callback: PyObjectRef) {}
|
||||
fn getvar(&self, arg: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyObjectRef> {
|
||||
// TODO: technically not thread safe
|
||||
let name = varname_converter(arg, vm)?;
|
||||
|
||||
let res = unsafe {
|
||||
tk_sys::Tcl_GetVar2Ex(
|
||||
self.interpreter,
|
||||
ptr::null(),
|
||||
name.as_ptr() as _,
|
||||
tk_sys::TCL_LEAVE_ERR_MSG as _,
|
||||
)
|
||||
};
|
||||
if res == ptr::null_mut() {
|
||||
todo!();
|
||||
}
|
||||
let res = if self.want_objects {
|
||||
self.from_object(res, vm)
|
||||
} else {
|
||||
self.unicode_from_object(res, vm)
|
||||
}?;
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn getint(&self, arg: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyObjectRef> {
|
||||
if let Some(int) = arg.downcast_ref::<PyInt>() {
|
||||
return Ok(PyObjectRef::from(vm.ctx.new_int(int.as_bigint().clone())));
|
||||
}
|
||||
|
||||
if let Some(obj) = arg.downcast_ref::<TclObject>() {
|
||||
let value = obj.value;
|
||||
unsafe { tk_sys::Tcl_IncrRefCount(value) };
|
||||
} else {
|
||||
todo!();
|
||||
}
|
||||
todo!();
|
||||
}
|
||||
// TODO: Fix arguments
|
||||
#[pymethod]
|
||||
fn mainloop(&self, threshold: Option<i32>) -> PyResult<()> {
|
||||
let threshold = threshold.unwrap_or(0);
|
||||
todo!();
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn quit(&self) {
|
||||
QUIT_MAIN_LOOP.store(true, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn create(args: TkAppConstructorArgs, vm: &VirtualMachine) -> PyResult<PyObjectRef> {
|
||||
unsafe {
|
||||
let interp = tk_sys::Tcl_CreateInterp();
|
||||
let want_objects = args.wantobjects != 0;
|
||||
let threaded = {
|
||||
let part1 = String::from("tcl_platform");
|
||||
let part2 = String::from("threaded");
|
||||
let part1_ptr = part1.as_ptr();
|
||||
let part2_ptr = part2.as_ptr();
|
||||
tk_sys::Tcl_GetVar2Ex(
|
||||
interp,
|
||||
part1_ptr as _,
|
||||
part2_ptr as _,
|
||||
tk_sys::TCL_GLOBAL_ONLY as ffi::c_int,
|
||||
)
|
||||
} != ptr::null_mut();
|
||||
let thread_id = tk_sys::Tcl_GetCurrentThread();
|
||||
let dispatching = false;
|
||||
let trace = None;
|
||||
// TODO: Handle threaded build
|
||||
let bool_str = String::from("oldBoolean");
|
||||
let old_boolean_type = tk_sys::Tcl_GetObjType(bool_str.as_ptr() as _);
|
||||
let (boolean_type, byte_array_type) = {
|
||||
let true_str = String::from("true");
|
||||
let mut value = *tk_sys::Tcl_NewStringObj(true_str.as_ptr() as _, -1);
|
||||
let mut bool_value = 0;
|
||||
tk_sys::Tcl_GetBooleanFromObj(interp, &mut value, &mut bool_value);
|
||||
let boolean_type = value.typePtr;
|
||||
tk_sys::Tcl_DecrRefCount(&mut value);
|
||||
|
||||
let mut value =
|
||||
*tk_sys::Tcl_NewByteArrayObj(&bool_value as *const i32 as *const u8, 1);
|
||||
let byte_array_type = value.typePtr;
|
||||
tk_sys::Tcl_DecrRefCount(&mut value);
|
||||
(boolean_type, byte_array_type)
|
||||
};
|
||||
let double_str = String::from("double");
|
||||
let double_type = tk_sys::Tcl_GetObjType(double_str.as_ptr() as _);
|
||||
let int_str = String::from("int");
|
||||
let int_type = tk_sys::Tcl_GetObjType(int_str.as_ptr() as _);
|
||||
let int_type = if int_type == ptr::null() {
|
||||
let mut value = *tk_sys::Tcl_NewIntObj(0);
|
||||
let res = value.typePtr;
|
||||
tk_sys::Tcl_DecrRefCount(&mut value);
|
||||
res
|
||||
} else {
|
||||
int_type
|
||||
};
|
||||
let wide_int_str = String::from("wideInt");
|
||||
let wide_int_type = tk_sys::Tcl_GetObjType(wide_int_str.as_ptr() as _);
|
||||
let bignum_str = String::from("bignum");
|
||||
let bignum_type = tk_sys::Tcl_GetObjType(bignum_str.as_ptr() as _);
|
||||
let list_str = String::from("list");
|
||||
let list_type = tk_sys::Tcl_GetObjType(list_str.as_ptr() as _);
|
||||
let string_str = String::from("string");
|
||||
let string_type = tk_sys::Tcl_GetObjType(string_str.as_ptr() as _);
|
||||
let utf32_str = String::from("utf32");
|
||||
let utf32_string_type = tk_sys::Tcl_GetObjType(utf32_str.as_ptr() as _);
|
||||
let pixel_str = String::from("pixel");
|
||||
let pixel_type = tk_sys::Tcl_GetObjType(pixel_str.as_ptr() as _);
|
||||
|
||||
let exit_str = String::from("exit");
|
||||
tk_sys::Tcl_DeleteCommand(interp, exit_str.as_ptr() as _);
|
||||
|
||||
if let Some(name) = args.screen_name {
|
||||
tk_sys::Tcl_SetVar2(
|
||||
interp,
|
||||
"env".as_ptr() as _,
|
||||
"DISPLAY".as_ptr() as _,
|
||||
name.as_ptr() as _,
|
||||
tk_sys::TCL_GLOBAL_ONLY as i32,
|
||||
);
|
||||
}
|
||||
|
||||
if args.interactive != 0 {
|
||||
tk_sys::Tcl_SetVar(
|
||||
interp,
|
||||
"tcl_interactive".as_ptr() as _,
|
||||
"1".as_ptr() as _,
|
||||
tk_sys::TCL_GLOBAL_ONLY as i32,
|
||||
);
|
||||
} else {
|
||||
tk_sys::Tcl_SetVar(
|
||||
interp,
|
||||
"tcl_interactive".as_ptr() as _,
|
||||
"0".as_ptr() as _,
|
||||
tk_sys::TCL_GLOBAL_ONLY as i32,
|
||||
);
|
||||
}
|
||||
|
||||
let argv0 = args.class_name.clone().to_lowercase();
|
||||
tk_sys::Tcl_SetVar(
|
||||
interp,
|
||||
"argv0".as_ptr() as _,
|
||||
argv0.as_ptr() as _,
|
||||
tk_sys::TCL_GLOBAL_ONLY as i32,
|
||||
);
|
||||
|
||||
if !args.want_tk {
|
||||
tk_sys::Tcl_SetVar(
|
||||
interp,
|
||||
"_tkinter_skip_tk_init".as_ptr() as _,
|
||||
"1".as_ptr() as _,
|
||||
tk_sys::TCL_GLOBAL_ONLY as i32,
|
||||
);
|
||||
}
|
||||
|
||||
if args.sync != 0 || args.use_.is_some() {
|
||||
let mut argv = String::with_capacity(4);
|
||||
if args.sync != 0 {
|
||||
argv.push_str("-sync");
|
||||
}
|
||||
if args.use_.is_some() {
|
||||
if args.sync != 0 {
|
||||
argv.push(' ');
|
||||
}
|
||||
argv.push_str("-use ");
|
||||
argv.push_str(&args.use_.unwrap());
|
||||
}
|
||||
argv.push_str("\0");
|
||||
let argv_ptr = argv.as_ptr() as *mut *mut i8;
|
||||
tk_sys::Tcl_SetVar(
|
||||
interp,
|
||||
"argv".as_ptr() as _,
|
||||
argv_ptr as *const i8,
|
||||
tk_sys::TCL_GLOBAL_ONLY as i32,
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
{
|
||||
let ret = std::env::var("TCL_LIBRARY");
|
||||
if ret.is_err() {
|
||||
let loc = _get_tcl_lib_path();
|
||||
std::env::set_var("TCL_LIBRARY", loc);
|
||||
}
|
||||
}
|
||||
|
||||
// Bindgen cannot handle Tcl_AppInit
|
||||
if tk_sys::Tcl_Init(interp) != tk_sys::TCL_OK as ffi::c_int {
|
||||
todo!("Tcl_Init failed");
|
||||
}
|
||||
|
||||
Ok(TkApp {
|
||||
interpreter: interp,
|
||||
want_objects,
|
||||
threaded,
|
||||
thread_id: Some(thread_id),
|
||||
dispatching,
|
||||
trace,
|
||||
old_boolean_type,
|
||||
boolean_type,
|
||||
byte_array_type,
|
||||
double_type,
|
||||
int_type,
|
||||
wide_int_type,
|
||||
bignum_type,
|
||||
list_type,
|
||||
string_type,
|
||||
utf32_string_type,
|
||||
pixel_type,
|
||||
}
|
||||
.into_pyobject(vm))
|
||||
}
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
const READABLE: i32 = tk_sys::TCL_READABLE as i32;
|
||||
#[pyattr]
|
||||
const WRITABLE: i32 = tk_sys::TCL_WRITABLE as i32;
|
||||
#[pyattr]
|
||||
const EXCEPTION: i32 = tk_sys::TCL_EXCEPTION as i32;
|
||||
|
||||
#[pyattr]
|
||||
const TIMER_EVENTS: i32 = tk_sys::TCL_TIMER_EVENTS as i32;
|
||||
#[pyattr]
|
||||
const IDLE_EVENTS: i32 = tk_sys::TCL_IDLE_EVENTS as i32;
|
||||
#[pyattr]
|
||||
const DONT_WAIT: i32 = tk_sys::TCL_DONT_WAIT as i32;
|
||||
}
|
||||
Reference in new issue
Block a user