1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// Copyright (c) 2023 Jonathan "Razordor" Alan Thomason
//! This macro is designed to make loading functions from `.dll`s, and `.so` files easy and convenient.
//! `dylink` can make use of the configuration predicate `any`, which can be used to fallback to alternative shared libraries as needed.
//!
//! # General Example
//! ```rust
//! use dylink::dylink;
//!
//! #[dylink(name = "Kernel32.dll")]
//! extern "system" {
//! fn GetLastError() -> u32;
//! }
//! ```
//!
//! # Vulkan Specialization
//! There is also a builtin vulkan loader option in the macro as well, which automatically looks for the shared library where expected.
//! The appropriate ABI to use with the vulkan loader is `extern "system"`.
//! ```rust
//! use dylink::dylink;
//!
//! # type VkInstanceCreateInfo = std::ffi::c_void;
//! # type VkAllocationCallbacks = std::ffi::c_void;
//! # type VkInstance = std::ffi::c_void;
//! # type VkResult = i32;
//! #[dylink(vulkan)]
//! extern "system" {
//! fn vkCreateInstance(
//! pCreateInfo: *const VkInstanceCreateInfo,
//! pAllocator: *const VkAllocationCallbacks,
//! pInstance: *mut VkInstance,
//! ) -> VkResult;
//! }
//! ```
//!
//! # Configuration Predicates
//! Dylink can also accept predicated disjunctions in an idiomatic manner by making use of the `any` function.
//! `any()` uses short-circuit logic to check for the existance of shared libraries.
//!
//! Note: `any()` only handles the library predicate, and not the function predicate.
//! This means that if the library is found, but the function is not, a panic will occur.
//! ```rust
//! #[dylink(any(name = "example_lib.so", name = "example_lib.so.1"))]
//! extern "C" {
//! fn my_function();
//! }
//! ```
use ;
use Lazy;
pub use *;
pub use *;
pub use ;
/// Macro for generating dynamically linked functions procedurally.
///
/// This macro supports all ABI strings that rust natively supports.
/// # Example
/// ```rust
/// # use dylink::dylink;
/// # type VkInstanceCreateInfo = std::ffi::c_void;
/// # type VkAllocationCallbacks = std::ffi::c_void;
/// # type VkInstance = std::ffi::c_void;
/// # type VkResult = i32;
/// #[dylink(vulkan)]
/// extern "system" {
/// fn vkCreateInstance(
/// pCreateInfo: *const VkInstanceCreateInfo,
/// pAllocator: *const VkAllocationCallbacks,
/// pInstance: *mut VkInstance,
/// ) -> VkResult;
/// }
/// ```
pub use dylink;
// I don't know how to implement wasm, so I'll just drop this here...
compile_error!;
// These globals are read every time a vulkan function is called for the first time,
// which occurs through `LazyFn::link`.
static VK_INSTANCE: RwLock =
new;
static VK_DEVICE: RwLock =
new;
// Used as a placeholder function pointer. This should **NEVER** be called directly,
// and promptly cast into the correct function pointer type.
pub type FnPtr = unsafe extern "system" fn ;
// The result of a dylink function
pub type Result<T> = Result;
// TODO: Make the `Global` struct below public when extern types are stable.
// The name `Global` is still TBD.
/// The global context for specializations.
///
/// This implicitly controls how the specialization `#[dylink(vulkan)]` handles function loading.
/// This Global is injected when building specializations, but is excluded when building generalizations,
/// such as `#[dylink(name = "my_lib.so")]`.
;