Seregon/zftpd

Zero-copy FTP/HTTP Daemon compatible with all POSIX systems

C/11.0 KB/No license
docs/ffi_usage.md
zftpd / docs / ffi_usage.md
1# zftpd FFI Usage Guide
2 
3The `zftpd` FFI (Foreign Function Interface) system allows you to integrate the FTP and HTTP servers, along with the memory manager, into other programming languages. It maintains the performance of the core C implementation while ensuring memory safety through idiomatic wrappers.
4 
5Currently, the system natively supports: **Rust**, **Python**, **Go**, and **Java (JNI)**.
6 
7## Compilation
8To compile the shared FFI library (`libzftpd_ffi.so` or `libzftpd_ffi.dylib`) and the respective bindings, use the `Makefile` and specify the desired languages:
9 
10```bash
11# Compile for Rust, Python, and Go
12make ffi_langs=rust,python,go
13```
14 
15The native output will be available in `build/<os>/<mode>/libzftpd_ffi.(so|dylib)`.
16 
17---
18 
19## 🦀 Rust
20Rust provides the fastest and safest bindings. Thanks to the `Drop` trait, C resources are automatically destroyed when they go out of scope.
21 
22### Setup
23Add the local path to your `Cargo.toml` or copy the `ffi/rust` folder.
24 
25### Usage Example
26```rust
27use zftpd::allocator::PalAlloc;
28use zftpd::ftp_server::FtpServer;
29 
30fn main() {
31 // 1. Initialize the allocator before any other operation
32 PalAlloc::init_default().expect("Failed to initialize allocator");
33 
34 // 2. Create and start the FTP server
35 // Returns a Result: safe to handle in case of bound ports
36 let server = FtpServer::new("127.0.0.1", 2121, "/var/ftp_root")
37 .expect("Failed to create FTP Server");
38 
39 server.start().expect("Failed to start FTP server");
40 println!("FTP Server running...");
41 
42 // 3. Stop the server (optional: it will be stopped by the Drop trait)
43 server.stop();
44
45 // You don't need to manually clean up memory: RAII handles everything.
46}
47```
48 
49---
50 
51## 🐍 Python
52Python uses `cffi` to interface with the C-core in out-of-line ABI mode. Context Managers allow you to manage resources cleanly, preventing memory leaks.
53 
54### Setup
55Ensure the compiled `libzftpd_ffi` library is located in `build/.../release/` or within your `LD_LIBRARY_PATH` (or `DYLD_LIBRARY_PATH` on macOS).
56 
57### Usage Example
58```python
59from zftpd.core import PalAlloc, FtpServer, ZftpdException
60 
61try:
62 # 1. Initialize the memory allocator
63 PalAlloc.init_default()
64 
65 # 2. Use Context Managers to guarantee the destruction of the C-Pointer
66 with FtpServer("127.0.0.1", 2121, "/var/ftp_root") as server:
67 server.start()
68 print(f"Server started. Active sessions: {server.active_sessions()}")
69
70 # ... logic ...
71
72 # At the end of the 'with' block, server.destroy() is called automatically!
73 
74except ZftpdException as e:
75 print(f"zftpd error: {e}")
76```
77 
78---
79 
80## 🐹 Go
81The Go bindings use `cgo` to communicate natively via structs.
82*Note*: Due to the nature of Go's garbage collector, you are responsible for closing the servers by calling `.Close()` when they are no longer needed.
83 
84### Usage Example
85```go
86package main
87 
88import (
89 "fmt"
90 "log"
91
92 // Import the local mapping
93 "zftpd_ffi/ffi/go/zftpd"
94)
95 
96func main() {
97 // 1. Initialize the allocator
98 if err := zftpd.PalAllocInitDefault(); err != nil {
99 log.Fatalf("Allocator error: %v", err)
100 }
101 
102 // 2. Errors reported idiomatically in Go style
103 server, err := zftpd.NewFtpServer("127.0.0.1", 2121, "/var/ftp_root")
104 if err != nil {
105 log.Fatalf("Unable to create server: %v", err)
106 }
107 // Correctly handle the closure of C pointers
108 defer server.Close()
109 
110 if err := server.Start(); err != nil {
111 log.Fatalf("Startup failed: %v", err)
112 }
113 
114 fmt.Println("FTP Server running!")
115 server.Stop()
116}
117```
118 
119---
120 
121## ☕ Java (JNI)
122The Java APIs encapsulate the JNI binding. They leverage the `AutoCloseable` interface to operate conveniently within `try-with-resources` blocks. If you do not use this construct, you will need to call `.close()` manually, as the garbage collector does not intervene on the C side until the JNI reference is destroyed.
123 
124### Usage Example
125```java
126import org.zftpd.ffi.PalAlloc;
127import org.zftpd.ffi.FtpServer;
128 
129public class Main {
130 public static void main(String[] args) {
131 // Load the native library and initialize the allocator
132 PalAlloc.initDefault();
133 
134 // Safe AutoCloseable implementation
135 try (FtpServer server = new FtpServer("127.0.0.1", 2121, "/var/ftp_root")) {
136
137 if (server.start() == 0) {
138 System.out.println("FTP Server started!");
139 }
140
141 // server.stop() / destroy() managed upon leaving the try block
142
143 } catch (Exception e) {
144 System.err.println("Error: " + e.getMessage());
145 }
146 }
147}
148```
149