Skip to content

Commit 121176e

Browse files
authored
Merge pull request #21 from marcbull/improve-callback
chore: allow closure as license callback
2 parents 1da08a4 + 6a737e9 commit 121176e

File tree

2 files changed

+44
-40
lines changed

2 files changed

+44
-40
lines changed

examples/license-activation.rs

+17-23
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,6 @@ use std::io::{self, BufRead}; // for user input (pause)
22

33
use lexactivator::*;
44

5-
pub type CallbackType = extern "C" fn(LexActivatorCode);
6-
7-
extern "C" fn license_callback(code: LexActivatorCode) {
8-
match code {
9-
LexActivatorCode::Status(status) => {
10-
match status {
11-
LexActivatorStatus::LA_OK => println!("License is active!"),
12-
LexActivatorStatus::LA_EXPIRED => println!("License has expired!"),
13-
LexActivatorStatus::LA_SUSPENDED => println!("License has been suspended!"),
14-
LexActivatorStatus::LA_GRACE_PERIOD_OVER => println!("License grace period is over!"),
15-
_ => println!("Unknown license status"),
16-
}
17-
}
18-
LexActivatorCode::Error(error) => {
19-
match error {
20-
LexActivatorError::LA_E_ACTIVATION_NOT_FOUND => println!("The license activation was deleted on the server."),
21-
_ => println!("Unknown error"),
22-
}
23-
}
24-
}
25-
}
26-
275
fn main() {
286
let product_data: String = "Product.dat_content".to_string();
297
let product_id: String = "Product_id".to_string();
@@ -53,7 +31,23 @@ fn main() {
5331
}
5432
}
5533
let callback_result: Result<(), LexActivatorError> =
56-
lexactivator::set_license_callback(license_callback);
34+
lexactivator::set_license_callback(|code| match code {
35+
LexActivatorCode::Status(status) => match status {
36+
LexActivatorStatus::LA_OK => println!("License is active!"),
37+
LexActivatorStatus::LA_EXPIRED => println!("License has expired!"),
38+
LexActivatorStatus::LA_SUSPENDED => println!("License has been suspended!"),
39+
LexActivatorStatus::LA_GRACE_PERIOD_OVER => {
40+
println!("License grace period is over!")
41+
}
42+
_ => println!("Unknown license status"),
43+
},
44+
LexActivatorCode::Error(error) => match error {
45+
LexActivatorError::LA_E_ACTIVATION_NOT_FOUND => {
46+
println!("The license activation was deleted on the server.")
47+
}
48+
_ => println!("Error: {}", error),
49+
},
50+
});
5751
println!("SetLicenseCallback: {:?}", callback_result);
5852

5953
let validation_result: Result<LexActivatorStatus, LexActivatorError> =

src/lib.rs

+27-17
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::ffi::*;
22
use serde::Deserialize;
3+
use std::sync::{LazyLock, Mutex};
34

45
mod extern_functions;
56
use extern_functions::*;
@@ -10,16 +11,16 @@ pub use error_codes::*;
1011
mod string_utils;
1112
use string_utils::*;
1213

13-
static mut CALLBACK_FUNCTION: Option<CallbackType> = None;
14+
type LicenseCallback = dyn Fn(LexActivatorCode) + Send + 'static;
1415

15-
pub type CallbackType = extern "C" fn(LexActivatorCode);
16+
static CALLBACK_FUNCTION: LazyLock<Mutex<Option<Box<LicenseCallback>>>> =
17+
LazyLock::new(|| Mutex::new(None));
1618

1719
extern "C" fn wrapper(code: i32) {
1820
let callback_status = LexActivatorCode::from_i32(code);
19-
unsafe {
20-
if let Some(callback) = CALLBACK_FUNCTION {
21-
callback(callback_status);
22-
}
21+
let callback = CALLBACK_FUNCTION.lock().unwrap();
22+
if let Some(callback) = callback.as_ref() {
23+
callback(callback_status);
2324
}
2425
}
2526

@@ -334,26 +335,28 @@ pub fn set_license_user_credential(email: String, password: String) -> Result<()
334335
}
335336
}
336337

337-
/// Sets the license callback function.
338-
///
339-
/// Whenever the server sync occurs in a separate thread, and server returns the response,
340-
/// license callback function gets invoked with the following status codes:
338+
/// Sets the license closure callback.
339+
///
340+
/// Whenever the server sync occurs in a separate thread, and server returns the response,
341+
/// license closure callback gets invoked with the following status codes:
341342
/// LA_OK, LA_EXPIRED, LA_SUSPENDED, LA_E_REVOKED, LA_E_ACTIVATION_NOT_FOUND, LA_E_MACHINE_FINGERPRINT
342-
/// LA_E_AUTHENTICATION_FAILED, LA_E_COUNTRY, LA_E_INET, LA_E_SERVER,LA_E_RATE_LIMIT, LA_E_IP,
343+
/// LA_E_AUTHENTICATION_FAILED, LA_E_COUNTRY, LA_E_INET, LA_E_SERVER,LA_E_RATE_LIMIT, LA_E_IP,
343344
/// LA_E_RELEASE_VERSION_NOT_ALLOWED, LA_E_RELEASE_VERSION_FORMAT
344345
///
345346
/// # Arguments
346347
///
347-
/// * `callback` - The callback function to be set.
348+
/// * `closure` - The closure callback to be set e.g. |code| { println!("{:?}", code) }
348349
///
349350
/// # Returns
350351
///
351-
/// Returns `Ok(())` if the license callback is set successfully, If an error occurs, an `Err` containing the `LexActivatorError`is returned.
352+
/// Returns `Ok(())` if the license closure callback is set successfully, If an error occurs, an `Err` containing the `LexActivatorError`is returned.
352353
353-
pub fn set_license_callback(callback: CallbackType) -> Result<(), LexActivatorError> {
354-
unsafe {
355-
CALLBACK_FUNCTION = Some(callback);
356-
}
354+
pub fn set_license_callback<F>(closure: F) -> Result<(), LexActivatorError>
355+
where
356+
F: Fn(LexActivatorCode) + Clone + Send + 'static,
357+
{
358+
let mut callback_function = CALLBACK_FUNCTION.lock().unwrap();
359+
callback_function.replace(Box::new(closure));
357360
let status: i32 = unsafe { SetLicenseCallback(wrapper) };
358361

359362
if status == 0 {
@@ -363,6 +366,13 @@ pub fn set_license_callback(callback: CallbackType) -> Result<(), LexActivatorEr
363366
}
364367
}
365368

369+
/// Unset the current license closure callback.
370+
371+
pub fn unset_license_callback() {
372+
let mut callback_function = CALLBACK_FUNCTION.lock().unwrap();
373+
*callback_function = None;
374+
}
375+
366376
/// Sets the activation lease duration.
367377
///
368378
/// # Arguments

0 commit comments

Comments
 (0)