在编写代码以使用Wayland Client API时,Rust似乎无法找到该wl_display_get_registry符号.该文件的objdump也无法找到该符号.但是,使用GCC编译的C程序能够找到该符号.
为什么C程序可以找到符号,但Rust不能?如何修复Rust程序以找到符号?
操作系统:Ubuntu 18.04 LTS
rustc -o wayland main.rs
Run Code Online (Sandbox Code Playgroud)
error: linking with `cc` failed: exit code: 1
|
= note: "cc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-m64" "-L" "/home/myrddin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "wayland.main0.rcgu.o" "wayland.main1.rcgu.o" "wayland.main2.rcgu.o" "wayland.main3.rcgu.o" "wayland.main4.rcgu.o" "-o" "wayland" "wayland.crate.allocator.rcgu.o" "-Wl,--gc-sections" "-pie" "-Wl,-z,relro,-z,now" "-nodefaultlibs" "-L" "/home/myrddin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-l" "wayland-client" "-Wl,--start-group" "-Wl,-Bstatic" "/home/myrddin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-2da986ecbb2c5327.rlib" "/home/myrddin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_unwind-57f46841c9a9f4ee.rlib" "/home/myrddin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc_jemalloc-23263fe5893322f6.rlib" "/home/myrddin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunwind-6ed5262c9a0a3e5a.rlib" "/home/myrddin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc_system-99c162b689d43349.rlib" "/home/myrddin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-cd415b85dd267875.rlib" "/home/myrddin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-3876ac10aa96a1e3.rlib" "/home/myrddin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd_unicode-598b0e9aca382e9a.rlib" "/home/myrddin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-4eabb2b1c31071b8.rlib" "-Wl,--end-group" "/home/myrddin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-d7a656735ceeae9e.rlib" "-Wl,-Bdynamic" "-l" "dl" "-l" "rt" "-l" "pthread" "-l" "pthread" "-l" "gcc_s" "-l" "c" "-l" "m" "-l" "rt" "-l" "pthread" "-l" "util" "-l" "util"
= note: wayland.main3.rcgu.o: In function `main::main':
main3-317d481089b8c8fe83113de504472633.rs:(.text._ZN4main4main17h52709beaa06fe157E+0x109): undefined reference to `wl_display_get_registry'
collect2: error: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)
pub enum WLDisplay {}
pub enum WLRegistry {}
#[link(name = "wayland-client")]
extern "C" {
pub fn wl_display_connect(name: *const ::std::os::raw::c_char) -> *mut WLDisplay;
pub fn wl_display_disconnect(display: *mut WLDisplay) -> ();
pub fn wl_display_get_registry(display: *mut WLDisplay) -> *mut WLRegistry;
}
fn main() {
let display: *mut WLDisplay;
let registry: *mut WLRegistry;
unsafe {
display = wl_display_connect(::std::ptr::null());
if display.is_null() == true {
eprintln!("Unable to connect to the Wayland display server.");
return;
}
println!("Connected to Wayland display server.");
println!("Retrieving the registry from the Wayland display.");
registry = wl_display_get_registry(display);
if registry.is_null() == true {
eprintln!("Unable to retrieve registry.");
} else {
println!("Registry retrieved.");
}
wl_display_disconnect(display);
println!("Disconnected from Wayland display server.");
}
}
Run Code Online (Sandbox Code Playgroud)
gcc -o wayland -lwayland-client main.c
Run Code Online (Sandbox Code Playgroud)
Connected to Wayland display server.
Retrieving the registry from the Wayland display.
Registry retrieved.
Disconnected from Wayland display server.
Run Code Online (Sandbox Code Playgroud)
#include <stdio.h>
#include <wayland-client.h>
int main()
{
struct wl_display *display;
struct wl_registry *registry;
display = wl_display_connect(NULL);
if (display == NULL)
{
fprintf(stderr, "Unable to connect to the Wayland display server.\n");
return 1;
}
fprintf(stdout, "Connected to Wayland display server.\n");
fprintf(stdout, "Retrieving the registry from the Wayland display.\n");
registry = wl_display_get_registry(display);
if (registry == NULL)
{
fprintf(stderr, "Unable to retrieve registry.\n");
}
else
{
fprintf(stdout, "Registry retrieved.\n");
}
wl_display_disconnect(display);
fprintf(stdout, "Disconnected from Wayland display server.\n");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
objdumpobjdump -TC /usr/lib/x86_64-linux-gnu/libwayland-client.so | grep "wl_display*"
Run Code Online (Sandbox Code Playgroud)
0000000000005f60 g DF .text 0000000000000275 Base wl_display_connect
0000000000006960 g DF .text 0000000000000078 Base wl_display_flush
0000000000006a90 g DF .text 000000000000000c Base wl_display_dispatch
00000000000067b0 g DF .text 0000000000000042 Base wl_display_cancel_read
00000000000068c0 g DF .text 000000000000000c Base wl_display_dispatch_pending
0000000000006800 g DF .text 00000000000000bf Base wl_display_dispatch_queue_pending
00000000000061e0 g DF .text 0000000000000057 Base wl_display_disconnect
0000000000006be0 g DF .text 00000000000000fc Base wl_display_roundtrip_queue
00000000000068d0 g DF .text 000000000000002c Base wl_display_get_error
0000000000005610 g DF .text 0000000000000031 Base wl_display_create_queue
0000000000006740 g DF .text 0000000000000052 Base wl_display_prepare_read_queue
0000000000006900 g DF .text 0000000000000051 Base wl_display_get_protocol_error
0000000000005dc0 g DF .text 0000000000000194 Base wl_display_connect_to_fd
00000000000069e0 g DF .text 00000000000000ac Base wl_display_dispatch_queue
0000000000006ce0 g DF .text 000000000000000c Base wl_display_roundtrip
0000000000006250 g DF .text 00000000000004f0 Base wl_display_read_events
0000000000006240 g DF .text 0000000000000004 Base wl_display_get_fd
000000000020dce0 g DO .data.rel.ro 0000000000000028 Base wl_display_interface
00000000000067a0 g DF .text 000000000000000c Base wl_display_prepare_read
Run Code Online (Sandbox Code Playgroud)
该wl_display_get_registry函数和其他几个函数标记static inline在头文件中wayland-client-protocols.h.标记的功能static inline不会导出其符号.这解释了C如何能够看到和使用该功能,但Rust无法做到.
我们必须重新实现C宏和静态内联函数作为Rust函数:
pub enum WLDisplay {}
pub enum WLProxy {}
pub enum WLRegistry {}
const WL_DISPLAY_GET_REGISTRY: ::std::os::raw::c_uint = 1;
#[link(name = "wayland-client")]
extern "C" {
#[no_mangle]
static wl_registry_interface: WLInterface;
pub fn wl_display_connect(name: *const ::std::os::raw::c_char) -> *mut WLDisplay;
pub fn wl_display_disconnect(display: *mut WLDisplay) -> ();
pub fn wl_proxy_marshal_constructor(
proxy: *mut WLProxy,
opcode: ::std::os::raw::c_uint,
interface: *const WLInterface,
) -> *mut WLProxy;
}
#[repr(C)]
pub struct WLMessage {
pub name: *const ::std::os::raw::c_char,
pub signature: *const ::std::os::raw::c_char,
pub types: *const *const WLInterface,
}
#[repr(C)]
pub struct WLInterface {
pub name: *const ::std::os::raw::c_char,
pub version: ::std::os::raw::c_int,
pub request_count: ::std::os::raw::c_int,
pub requests: *const WLMessage,
pub event_count: ::std::os::raw::c_int,
pub events: *const WLMessage,
}
fn wl_display_get_registry(display: *mut WLDisplay) -> *mut WLRegistry {
let proxy: *mut WLProxy;
unsafe {
proxy = wl_proxy_marshal_constructor(
display as *mut _ as *mut WLProxy,
WL_DISPLAY_GET_REGISTRY,
&wl_registry_interface,
);
proxy as *mut _ as *mut WLRegistry
}
}
fn main() {
let display: *mut WLDisplay;
let registry: *mut WLRegistry;
unsafe {
display = wl_display_connect(::std::ptr::null());
if display.is_null() == true {
eprintln!("Unable to connect to the Wayland display server.");
return;
}
println!("Connected to Wayland display server.");
println!("Retrieving the registry from the Wayland display.");
registry = wl_display_get_registry(display);
if registry.is_null() == true {
eprintln!("Unable to retrieve registry.");
} else {
println!("Registry retrieved.");
}
wl_display_disconnect(display);
println!("Disconnected from Wayland display server.");
}
}
Run Code Online (Sandbox Code Playgroud)