【发布时间】:2016-04-06 23:30:58
【问题描述】:
这是我的源代码:
extern crate user32;
extern crate kernel32;
use std::io::prelude::*;
use std::net::TcpStream;
use std::ptr;
fn main() {
let mut message = get_data();
loop {
if message != get_data() {
let mut client = TcpStream::connect("127.0.0.1:8080").unwrap();
message = get_data();
println!("{}", message);
let _ = client.write(message.as_bytes());
println!("Sent!");
}
}
}
fn get_data() -> String {
let value: String;
unsafe {
let open = user32::OpenClipboard(ptr::null_mut());
if open == 0 {
println!("{}", kernel32::GetLastError());
user32::CloseClipboard();
return "NULL".to_string()
}
let var = user32::GetClipboardData(13 as u32);
if var.is_null() {
println!("{}", kernel32::GetLastError());
user32::CloseClipboard();
return "NULL".to_string()
}
let data = kernel32::GlobalLock(var) as *mut u16;
let len = rust_strlen16(data);
let raws = std::slice::from_raw_parts(data, len);
value = String::from_utf16_lossy(raws);
kernel32::GlobalUnlock(var);
user32::CloseClipboard();
}
value
}
#[inline(always)] // used from clipboard-win, not mine
unsafe fn rust_strlen16(buff_p: *mut u16) -> usize {
let mut i: isize = 0;
while *buff_p.offset(i) != 0 {
i += 1;
}
return i as usize
}
当我在 main 的第 1 行初始化 message 时,一切都很好,但是当我开始复制文本时,事情开始变得有点奇怪。
从get_data() 中的OpenClipboard 函数,我从GetLastError 得到的错误可能是6 (ERROR_INVALID_HANDLE) 或5 (ERROR_ACCESS_DENIED),原因不明。
从GetClipboardData 函数中,我始终会从GetLastError 得到错误代码1418 (ERROR_CLIPBOARD_NOT_OPEN)。你会认为我会从OpenClipboard 获取错误代码 6 或 5 得到这个错误,但是它不会打印 1418,因为它不能在函数中走那么远,对吧?我可能错了,但我就是这么看的。
您还应该注意的是,在循环中比较 message 时会出现这些错误,但 if 语句仍然继续,并且消息被分配实际复制的数据,这里是一些示例输出。
1418 // this is when message and get_data() are being checked
println!("{}", result); // this is the actual copied data which is message
Sent! // sent!
5
NULL
Sent!
println!("Got Connection");
Sent!
【问题讨论】:
-
作为
user32和kernel32crates 的作者,我可以自信地说没有互操作。它们是直接链接到系统库的原始直接调用。零包装,相当于在 C 中使用它们。 -
@retep998 这是一个奇怪的问题。我什至让代码进入无限循环,这取决于我是否有
println!。某处有什么东西被弄脏了…… -
呃,别管我的最后一件事了。正如@DavidHeffernan 所指出的,
println!最终必须调用改变GetLastError的东西。在 WinAPI 函数和对GetLastError的调用之间使用println!是个坏主意。 -
@Shep 我希望在调用函数之前准备好参数
-
@DavidHeffernan 我有类似
WinApiCall(); println!(); GetLastError();的东西,事后看来这是一件非常愚蠢的事情^_^。这当然让我感到困惑。根据GetLastError的说法,在纠正了我自己的错误后,我仍然看到“打开”剪贴板未打开的问题。