0

I'm trying to use the Windows API to write a Windows GUI program, using thread_local to save all the created windows or buttons.

use std::thread::Thread;
use std::rc::Rc;
use std::cell::RefCell;
use std::collections::HashMap;

// button window checkbox need impl this trait.
trait Wnd{
    fn CreateWindow(&self)->int
    {
        // do some thing
        0
    }
}

pub struct Dust{
  window_counter:int,
  hInstance:int,
  hookId: int,
  widgets:HashMap<int, Rc<RefCell<Wnd>>>,
}

fn dust()->RefCell<Dust>{
  unsafe{
    let mut d = Dust{
      window_counter:0,
      hInstance:0,
      hookId:0,
      widgets: HashMap::new(),
    };

    return RefCell::new(d)
  }
}

pub thread_local!(static TLS_DUST: RefCell<Dust> = dust());


fn main()
{

    TLS_DUST.with( | d | {
        let mut dust = d.borrow_mut();
        dust.window_counter-=1;
    });

}

when I build I got the error:

$ cargo build --verbose
   Compiling dust v0.0.1 (file:///D:/msys64/home/BYWAYBOY/dust/examples)
     Running `rustc D:\msys64\home\BYWAYBOY\dust\src\lib.rs --crate-name dust --crate-type lib -g -C metadata=3fbf7f518595f4d2 -C extra-filename=-3fbf7f518595f4d2 --out-dir D:\msys64\home\BYWAYBOY\dust\examples\target\deps --emit=dep-info,link -L D:\msys64\home\BYWAYBOY\dust\examples\target\deps -L D:\msys64\home\BYWAYBOY\dust\examples\target\deps`
D:\msys64\home\BYWAYBOY\dust\src\lib.rs:52:36: 52:39 error: explicit lifetime bound required
D:\msys64\home\BYWAYBOY\dust\src\lib.rs:52   widgets:HashMap<HWND, Rc<RefCell<Wnd>>>,
                                                                              ^~~
error: aborting due to previous error
Could not compile `dust`.

Caused by:
  Process didn't exit successfully: `rustc D:\msys64\home\BYWAYBOY\dust\src\lib.rs --crate-name dust --crate-type lib -g -C metadata=3fbf7f518595f4d2 -C extra-filename=-3fbf7f518595f4d2 --out-dir D:\msys64\home\BYWAYBOY\dust\examples\target\deps --emit=dep-info,link -L D:\msys64\home\BYWAYBOY\dust\examples\target\deps -L D:\msys64\home\BYWAYBOY\dust\examples\target\deps` (status=101)

I just want use the HashMap to store all windows and widgets in a thread_local.

Vladimir Matveev
  • 120,085
  • 34
  • 287
  • 296
bywayboy
  • 3
  • 4

1 Answers1

1

Here is a rust playpen with a version of your code that compiles: http://is.gd/1vAihA

Below is the code copied from the playpen, let me explain what I changed.

The error that you mention above was coming from your Dust struct declaration, specifically the widgets field. Wnd is a trait, and the type of the widget field is using the trait object type. The trait object type allows for dynamic dispatch during runtime, however, as the compiler says, you need to specify a lifetime bound on the trait object.

I specified the special lifetime bound, static, because you are using this with the thread_local! macro and declaring TLS_DUST as static. 'static essentially says that this variable will live for the entire lifetime of the program.

After that error was fixed, rustc hit another error related to Wnd not being of kind Sized. Sized is a kind that specifies that a type has a known size at compile-time. Since Wnd is a trait object and thus could potentially be any number of different sizes, we have to wrap it in a Box<T> (think of Box<T> as a unique pointer type).

I also took the opportunity to write an impl for Dust. This is a more idiomatic way of creating a new variable of some type, Dust::new(). I kept your dust() function to wrap the new Dust struct in a RefCell.

Finally, I fixed some rustc warnings related to camel case code, rust usually uses underscores to separate words.

Code:

use std::thread::Thread;
use std::rc::Rc;
use std::cell::RefCell;
use std::collections::HashMap;

// button window checkbox need impl this trait.
trait Wnd {
    fn create_window(&self) -> int
    {
        // do some thing
        0
    }
}

struct Dust {
  window_counter: int,
  h_instance: int,
  hook_id: int,
  widgets: HashMap<int, Rc<RefCell<Box<Wnd + 'static>>>>, //'
}

impl Dust {
    fn new() -> Dust {
        Dust {
            window_counter:0,
            h_instance:0,
            hook_id:0,
            widgets: HashMap::new(),
        }
    }

    fn dust() -> RefCell<Dust> {
        RefCell::new(Dust::new())
    }
}

pub thread_local!(static TLS_DUST: RefCell<Dust> = Dust::dust());

fn main()
{
    TLS_DUST.with( | d | {
        let mut dust = d.borrow_mut();
        dust.window_counter-=1;
    });
}
crhino
  • 549
  • 3
  • 9