-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Investigation] Read string data using CLFN (and pass out string pointer separately) #3
Comments
This is far from ready yet but my goal with the labVIEW interop crate (https://github.com/WiresmithTech/Rust-LabVIEW-Interop) would be that you can pass the string handle into rust and it could handle resizing and perhaps encoding differences. Right now though I've not started on it so there is some work to be done first! |
@JamesMc86 Yes, it would be nice to have an easy way to work with a LabVIEW string handle in Rust. I think you're right that doing the string resizing in Rust would make things nice and simple in LabVIEW. Question: how does one access the LabVIEW memory manager on the Rust side of things? Would Rust call into |
Yep that's it. I've not got as far as trying it but I think you can dynamically load the functions assuming it is running inside LabVIEW. I've looked in principle but not got as far as trying it
James McNally
Director/Systems Engineer
Wiresmith Technology
t: 01635 597171
…________________________________
From: Jim Kring ***@***.***>
Sent: Thursday, June 22, 2023 2:46:25 PM
To: JKISoftware/toml-edit-labview ***@***.***>
Cc: James McNally ***@***.***>; Mention ***@***.***>
Subject: Re: [JKISoftware/toml-edit-labview] [Investigation] Read string data using CLFN (and pass out string pointer separately) (Issue #3)
@JamesMc86<https://github.com/JamesMc86> Yes, it would be nice to have an easy way to work with a LabVIEW string handle in Rust. I think you're right that doing the string resizing in Rust would make things nice and simple in LabVIEW. Question: how does one access the LabVIEW memory manager on the Rust side of things? Would Rust call into LabVIEW.exe and access its exported functions similar to how we can do this with a call library function node?
—
Reply to this email directly, view it on GitHub<#3 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/ABBTHYHND7GFDEG6LWH2KFTXMREDDANCNFSM6AAAAAAZPJPOCY>.
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
I see. It looks like this is the way that would work... |
@JamesMc86 I was able to get this far... // exported function that calls into LabVIEW.exe's memory manager
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn labview_get_string_size(
labview_path: *const c_char,
string_to_size: *const c_char,
) -> u32 {
let labview_path = unsafe { CStr::from_ptr(labview_path).to_string_lossy().into_owned() };
let labview_lib = match unsafe { libloading::Library::new(labview_path.clone().as_str()) } {
Ok(lib) => lib,
Err(_) => {
println!("Unable to load LabVIEW.exe");
return 0;
}
};
// the DSGetHandleSize function is exported from LabVIEW.exe and takes a handle as an argument
let DSGetHandleSize: libloading::Symbol<unsafe extern "C" fn(*const c_char) -> u32> =
match unsafe { labview_lib.get(b"DSGetHandleSize") } {
// will get back Result<Symbol<'_, _>, Error>
Ok(func) => func,
Err(_) => {
println!("Unable to find DSGetHandleSize function in LabVIEW.exe");
return 0;
}
};
let handle_size = unsafe { DSGetHandleSize(string_to_size) };
return handle_size;
} |
Looks good. I think there is a way that you can do it without the path to LabVIEW but will have to remember where I've seen it. Bit because it is already in memory you can grab it from there
James McNally
Director/Systems Engineer
Wiresmith Technology
t: 01635 597171
…________________________________
From: Jim Kring ***@***.***>
Sent: Friday, June 23, 2023 4:56:16 AM
To: JKISoftware/toml-edit-labview ***@***.***>
Cc: James McNally ***@***.***>; Mention ***@***.***>
Subject: Re: [JKISoftware/toml-edit-labview] [Investigation] Read string data using CLFN (and pass out string pointer separately) (Issue #3)
@JamesMc86<https://github.com/JamesMc86> I was able to get this far...
[image]<https://user-images.githubusercontent.com/381432/248149319-613cafa9-0e5e-495c-b0f7-b30067dc0d32.png>
// exported function that calls into LabVIEW.exe's memory manager
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn labview_get_string_size (
labview_path: *const c_char,
string_to_size: *const c_char,
) -> u32 {
let labview_path = unsafe { CStr::from_ptr(labview_path).to_string_lossy().into_owned() };
let labview_lib = match unsafe { libloading::Library::new(labview_path.clone().as_str()) } {
Ok(lib) => lib,
Err(_) => {
println!("Unable to load LabVIEW.exe");
return 0;
}
};
// the DSGetHandleSize function is exported from LabVIEW.exe and takes a handle as an argument
let DSGetHandleSize: libloading::Symbol<unsafe extern fn(*const c_char) -> u32> = match unsafe { labview_lib.get(b"DSGetHandleSize") } {
// will get back Result<Symbol<'_, _>, Error>
Ok(func) => func,
Err(_) => {
println!("Unable to find DSGetHandleSize function in LabVIEW.exe");
return 0;
}
};
let handle_size = unsafe { DSGetHandleSize(string_to_size) };
return handle_size
}
—
Reply to this email directly, view it on GitHub<#3 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/ABBTHYDPXWXF3LUOH5O6POLXMUHWBANCNFSM6AAAAAAZPJPOCY>.
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
Yes, I was thinking that it must be possible to get the name from memory. I
guess another consideration is that we would want this to work in a built
EXE, which means that the application/executable name (and path) would be
different that for the LabVIEW IDE.
|
I tried just using the name "LabVIEW.exe" instead of the full path and it worked fine:
|
And, here's a little gem ( use std::env
let exe_path = match env::current_exe() {
Ok(exe_path) => exe_path,
Err(e) => {
println!("failed to get current exe path");
return 1;
},
};
let labview_lib = match unsafe { libloading::Library::new(exe_path) } {
Ok(lib) => lib,
Err(_) => {
println!("Unable to load LabVIEW.exe");
return 42;
}
}; |
When I've gon digging for the interop crate this is the nicest solution I found and seems to be working.
Initial testing looks good - unsure about error handling in the constructor. Right now it would panic but unclear if there is an expected way to handle this. Code is in https://github.com/WiresmithTech/Rust-LabVIEW-Interop/blob/main/labview-interop/src/labview.rs Now I have that worked out string handling is next on my list so hopefully you might be able to just pull from the interop crate soon if you want |
Current Approach - Read String using LabVIEW's MoveBlock functionality (before closing reference)
Here is the VI that reads a cstring from a memory location:
The MoveBlock function is exported by the LabVIEW executable app:
After we're done reading the data, we close the reference:
Different Approach - Use CLFN to Read String, but also pass string reference (so we can close reference)
A slightly different approach to reading string data from Rust is to have the CLFN read the string data (instead of just getting the address of the data and reading it with the Memory Manager). This is nice, because we can rely on LabVIEW's built in feature for reading a cstring, however, it means that we must also pass out the string's address, separately, so that we can ask Rust to deallocate/free the string after LabVIEW has read the data.
That looks something like this:
When we call this from LabVIEW, we can read the return string using the built in CLFN's
C String Pointer
format for strings.And, we will ALSO get the address of the string as an integer that we can pass back to Rust to deallocate/free, using the
cstring_free_memory()
function shown below:The text was updated successfully, but these errors were encountered: