Skip to content

Commit

Permalink
Updated Rust (third party) example
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrej123456789 committed Oct 4, 2024
1 parent a82d5ac commit 515cc75
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 33 deletions.
40 changes: 23 additions & 17 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ VOID example(const std::vector<std::string>& vect)
2. Copy `AddLog` and `LoadDynamicLibrary` functions.
```cpp
template <typename T>
int LoadDynamicLibrary(const char* path, const char* function, T value)
int LoadDynamicLibrary(const char* path, const char* function, T argument)
{
void *handle;
void (*func)(T);
Expand All @@ -153,20 +153,20 @@ VOID example(const std::vector<std::string>& vect)
}
func = reinterpret_cast<void (*)(T)>(dlsym(handle, function));
if ((error = dlerror()) != NULL)
if ((error = dlerror()) != NULL)
{
fputs(error, stderr);
return 1;
}
(*func)(value);
(*func)(argument);
dlclose(handle);
return 0;
}
// Explicitly instantiate a template if `LoadDynamicLibrary()` function has to be called from extern "C" block
template int LoadDynamicLibrary<const char*>(const char* path, const char* function, const char* value);
// This explicit template instantiation is making `LoadDynamicLibrary` function available from extern "C" block
template int LoadDynamicLibrary<const char*>(const char* path, const char* function, const char* argument);
void AddLog(std::string fmt, ...)
{
Expand All @@ -193,15 +193,12 @@ VOID example(const std::vector<std::string>& vect)
4. Replace all other functions for printing to console (like `printf`, `std::cout`, etc.) to `AddLog` function. `AddLog` works like `printf`.
5. Compile and use Termi's `loadtp` command to test it!
*`loadtp` only accepts one `const char*` argument so do parsing inside your program!*
*Passed argument to a third party commands/applications using `loadtp` command is one combined string. Do parsing inside your command/application, arguments are separated by space.program!*
## For those who want to know more
### Port application written in Rust
1. Follow "C++ steps" to create new core command.
2. Create new `LoadRust` function (just copy previous one, change name and path of .dll file).
3. Replace command code (in `Termi-Commands`) by your `LoadRust` function.
4. Create new Rust library by using cargo - `cargo new --lib name`.
5. Change `Cargo.toml` content to (change `name` and `version`):
1. Create new Rust library by using cargo - `cargo new --lib name`.
2. Change `Cargo.toml` content to (change `name` and `version`):
```c
[package]
name = "your package name"
Expand All @@ -215,7 +212,7 @@ crate-type = ["cdylib"]
libloading = "0.7"
```

6. Change `lib.rs` content to (change path to .dll or .so file):
3. Change `lib.rs` content to (change path to .dll or .so file):
```rs
#![allow(non_snake_case)]

Expand All @@ -224,6 +221,7 @@ use libloading::{Library, Symbol};
use std::ffi::{CStr, CString};
use std::os::raw::c_char;

/// `printf()` for Termi's console
fn AddLog(fmt: &CStr) {
unsafe {
let lib = Library::new("path do .dll or .so file").unwrap();
Expand All @@ -235,12 +233,21 @@ fn AddLog(fmt: &CStr) {
}
}

fn GetArgument(arg: *const c_char) -> CString {
/// Separate string into arguments intended for this Rust program
///
/// Returns vector of `CString`
fn GetArguments(arg: *const c_char) -> Vec<CString> {
let mut vec = Vec::new();

let arg_buf = unsafe { CStr::from_ptr(arg) };
let arg_str = arg_buf.to_str().unwrap();
let argument = CString::new(arg_str).expect("CString::new failed!");

return argument;
for word in arg_str.split(' ') {
let c_string = CString::new(word).expect("Failed to create CString");
vec.push(c_string);
}

return vec;
}

#[no_mangle]
Expand All @@ -253,8 +260,7 @@ pub extern "C" fn rust_function(arg: *const c_char) {

```

### Note/Notes
1. Passed argument to third party commands/applications is one combined string. Do parsing inside your command/application, arguments are separated by space.
*Passed argument to a third party commands/applications using `loadtp` command is one combined string. Do parsing inside your command/application, arguments are separated by space.program!*

### Informations about elements in vector:
```cpp
Expand Down
45 changes: 29 additions & 16 deletions src/rtest/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,17 @@ use libloading::{Library, Symbol};
use std::ffi::{CStr, CString};
use std::os::raw::c_char;

fn AddLog(fmt: &CStr) {
#[cfg(target_os = "windows")]
unsafe {
let lib = Library::new("Termi-GUI.so").unwrap();
let foo = lib
.get::<Symbol<extern "C" fn(*const c_char)>>(b"AddLog")
.unwrap();
#[cfg(target_os = "windows")]
const GUI_PATH: &str = "Termi-GUI.dll";

foo(fmt.as_ptr());
}
#[cfg(any(target_os="macos", target_os = "linux", target_os = "freebsd",
target_os = "openbsd", target_os = "netbsd"))]
const GUI_PATH: &str = "libTermi-GUI.so";

#[cfg(target_os = "linux")]
/// `printf()` for Termi's console
fn AddLog(fmt: &CStr) {
unsafe {
let lib = Library::new("libTermi-GUI.so").unwrap();
let lib = Library::new(GUI_PATH).unwrap();
let foo = lib
.get::<Symbol<extern "C" fn(*const c_char)>>(b"AddLog")
.unwrap();
Expand All @@ -27,12 +24,21 @@ fn AddLog(fmt: &CStr) {
}
}

fn GetArgument(arg: *const c_char) -> CString {
/// Separate string into arguments intended for this Rust program
///
/// Returns vector of `CString`
fn GetArguments(arg: *const c_char) -> Vec<CString> {
let mut vec = Vec::new();

let arg_buf = unsafe { CStr::from_ptr(arg) };
let arg_str = arg_buf.to_str().unwrap();
let argument = CString::new(arg_str).expect("CString::new failed!");

return argument;
for word in arg_str.split(' ') {
let c_string = CString::new(word).expect("CString::new failed!");
vec.push(c_string);
}

return vec;
}

#[no_mangle]
Expand All @@ -42,15 +48,22 @@ pub extern "C" fn rust_function(arg: *const c_char) {
while i < 3000 {
let num_str = CString::new("y").expect("CString::new failed!");
AddLog(&num_str);

i += 1;
}

let new_line = CString::new("\n").expect("CString::new failed!");
let text = CString::new("This function is called from Rust programming langauge")
let text = CString::new("This function is called from Rust programming language")
.expect("CString::new failed!");


AddLog(&new_line);
AddLog(&text);
AddLog(&GetArgument(arg));

let arguments_list_line = CString::new("Arguments:").expect("CString::new failed!");
AddLog(&arguments_list_line);

for argument in GetArguments(arg) {
AddLog(&argument);
}
}

0 comments on commit 515cc75

Please sign in to comment.