doc:Rust-to-LLGO-Migration-Guide.md
This commit is contained in:
125
doc/Rust-to-LLGO-Migration-Guide.md
Normal file
125
doc/Rust-to-LLGO-Migration-Guide.md
Normal file
@@ -0,0 +1,125 @@
|
||||
# Rust to LLGO Migration Document
|
||||
|
||||
### Add Dependencies & Build Configuration
|
||||
|
||||
Edit `Cargo.toml` to include necessary dependencies and configuration:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
libc = "0.2"
|
||||
csv = "1.1"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"] # The generated dynamic library will conform to the C standard
|
||||
```
|
||||
|
||||
### Import C Language Types
|
||||
|
||||
Use types from the libc package for interoperability with C:
|
||||
|
||||
```rust
|
||||
use libc::{c_int, c_char, strlen};
|
||||
```
|
||||
|
||||
### Function Decoration and Attributes
|
||||
|
||||
To ensure that Rust functions can be correctly called by C and LLGO, use the following decorators:
|
||||
|
||||
- `#[no_mangle]` prevents the compiler from mangling the function name.
|
||||
|
||||
- `unsafe` is used to mark operations that are unsafe, especially when dealing with raw pointers.
|
||||
|
||||
- `extern "C"` specifies the use of C calling conventions.
|
||||
|
||||
### Memory Management
|
||||
|
||||
Use `Box` to manage dynamic memory to ensure correct memory release between Rust and C:
|
||||
|
||||
```rust
|
||||
pub unsafe extern "C" fn sled_create_config() -> \*mut Config {
|
||||
Box::into_raw(Box::new(Config::new()))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sled_free_config(config: \*mut Config) {
|
||||
drop(Box::from_raw(config));
|
||||
}
|
||||
```
|
||||
|
||||
### Handling Generic Pointers
|
||||
|
||||
Address the interfacing issues between generic pointers in C and Rust:
|
||||
|
||||
```rust
|
||||
#[no_mangle]
|
||||
pub extern "C" fn csv_reader_new(file_path: *const c_char) -> *mut c_void { /* ... */ }
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn csv_reader_free(ptr: *mut c_void) { /* ... */ }
|
||||
```
|
||||
|
||||
### String Handling
|
||||
|
||||
Convert strings between C and Rust:
|
||||
|
||||
```rust
|
||||
#[no_mangle]
|
||||
pub extern "C" fn csv_reader_read_record(ptr: *mut c_void) -> *const c_char { /* ... */ }
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn free_string(s: *mut c_char) {
|
||||
unsafe {
|
||||
let c_string = CString::from_raw(s);
|
||||
drop(c_string);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Compilation and Installation
|
||||
|
||||
Build the dynamic library and use `dylib-installer` to install it to the system path:
|
||||
|
||||
```sh
|
||||
cargo build --release
|
||||
cargo install --git https://github.com/hackerchai/dylib-installer
|
||||
sudo dylib_installer ./target/release/
|
||||
```
|
||||
|
||||
### Generate Header File
|
||||
|
||||
Use cbindgen to generate a C header file, automating this process through a `build.rs` script:
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
let config = cbindgen::Config::from_file("cbindgen.toml").expect("Config file not found.");
|
||||
cbindgen::generate_with_config(&crate_dir, config).unwrap().write_to_file("target/include/csv_wrapper.h");
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### LLGO Package Mapping
|
||||
|
||||
Map functions from the Rust library to an LLGO package, ensuring type consistency:
|
||||
|
||||
```go
|
||||
const (
|
||||
LLGoPackage = "link: $(pkg-config --libs csv_wrapper); -lcsv_wrapper"
|
||||
)
|
||||
|
||||
type Reader struct {
|
||||
Unused [8]byte
|
||||
}
|
||||
|
||||
//go:linkname NewReader C.csv_reader_new
|
||||
func NewReader(file_path *c.Char) *Reader
|
||||
|
||||
//llgo:link (*Reader).Free C.csv_reader_free
|
||||
func (reader *Reader) Free() {}
|
||||
|
||||
//llgo:link (*Reader).ReadRecord C.csv_reader_read_record
|
||||
func (reader *Reader) ReadRecord() *c.Char { return nil }
|
||||
```
|
||||
|
||||
### Writing Examples and README
|
||||
|
||||
Provide example code and a detailed README file to help users understand how to use the generated library.
|
||||
Reference in New Issue
Block a user