endurox-sys

Crates.ioendurox-sys
lib.rsendurox-sys
version0.1.1
created_at2025-11-08 19:39:44.171535+00
updated_at2025-11-08 21:16:03.097159+00
descriptionLow-level FFI bindings for Enduro/X middleware
homepagehttps://github.com/serdzz/endurox-rust
repositoryhttps://github.com/serdzz/endurox-rust
max_upload_size
id1923206
size74,976
(serdzz)

documentation

https://docs.rs/endurox-sys

README

endurox-sys

Low-level Rust FFI bindings for Enduro/X middleware.

Enduro/X is a high-performance, open-source middleware platform that implements the XATMI API. This crate provides safe and unsafe Rust bindings to the Enduro/X C API, enabling you to build distributed transaction processing applications in Rust.

Features

  • XATMI API - Complete bindings for tpcall(), tpacall(), tpreturn(), etc.
  • UBF Buffers - Typed buffer manipulation with Bchg(), Bget(), etc.
  • Server Development - Build Enduro/X servers with atmisrvnomain()
  • Client Development - Create clients with tpinit(), tpterm()
  • Derive Macros - Optional #[derive(UbfStructDerive)] for automatic serialization
  • Type Safety - Safe wrappers around raw pointers and error handling

Installation

Add this to your Cargo.toml:

[dependencies]
endurox-sys = { version = "0.1", features = ["ubf", "server"] }

Prerequisites

  • Enduro/X middleware installed and configured
  • Required environment variables (see below)
  • Oracle Instant Client (if using Oracle features)

Environment Variables

NDRX_HOME (Required)

Points to the Enduro/X installation directory. Used by the build script to locate Enduro/X libraries and headers.

export NDRX_HOME=/opt/endurox

The build script uses this to:

  • Link against Enduro/X libraries (libatmi, libubf, libnstd, etc.)
  • Find header files during compilation

NDRX_APPHOME (Optional)

Points to your application's home directory. Used by the build script to locate UBF field table definitions (ubftab/ directory) for generating Rust constants.

export NDRX_APPHOME=/path/to/your/app

When set, the build script looks for *.fd.h files in $NDRX_APPHOME/ubftab/ and generates Rust constants for UBF field IDs. This allows you to use field constants like T_NAME_FLD directly in your code.

Build-time behavior:

  • If NDRX_APPHOME is set: looks for $NDRX_APPHOME/ubftab/*.fd.h
  • If not set: looks for ../ubftab/*.fd.h (relative to crate directory, for local development)
  • If no UBF tables found: generates empty constants file (build still succeeds)

Example:

use endurox_sys::*;

unsafe {
    // Use generated field constants
    Bchg(buffer, T_NAME_FLD, 0, name.as_ptr() as *mut i8, 0);
    Bchg(buffer, T_AMOUNT_FLD, 0, &amount as *const _ as *mut i8, 0);
}

Usage

Basic Client Example

use endurox_sys::*;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    unsafe {
        // Initialize connection
        tpinit(std::ptr::null_mut())?;
        
        // Allocate UBF buffer
        let buf = tpalloc(b"UBF\0".as_ptr() as *mut i8, std::ptr::null_mut(), 1024);
        
        // Call service
        let mut len = 1024;
        tpcall(
            b"MYSERVICE\0".as_ptr() as *mut i8,
            buf,
            0,
            &mut buf,
            &mut len,
            0
        )?;
        
        // Free buffer and disconnect
        tpfree(buf);
        tpterm();
    }
    
    Ok(())
}

Server Example with Derive

use endurox_sys::*;

#[derive(UbfStructDerive)]
struct Request {
    #[ubf_field(1000)]
    transaction_id: String,
    
    #[ubf_field(1001)]
    amount: i64,
}

#[derive(UbfStructDerive)]
struct Response {
    #[ubf_field(2000)]
    status: String,
    
    #[ubf_field(2001)]
    message: String,
}

#[no_mangle]
pub extern "C" fn MYSERVICE(p_svc: *mut TPSVCINFO) {
    unsafe {
        let svc = &*p_svc;
        
        // Deserialize request
        let req = match Request::from_ubf(svc.data as *mut UBFH) {
            Ok(r) => r,
            Err(_) => {
                tpreturn(TPFAIL, 0, std::ptr::null_mut(), 0, 0);
                return;
            }
        };
        
        // Process request
        let resp = Response {
            status: "SUCCESS".to_string(),
            message: format!("Processed {}", req.transaction_id),
        };
        
        // Serialize response
        if resp.to_ubf(svc.data as *mut UBFH).is_ok() {
            tpreturn(TPSUCCESS, 0, svc.data, 0, 0);
        } else {
            tpreturn(TPFAIL, 0, std::ptr::null_mut(), 0, 0);
        }
    }
}

Features

ubf

Enables UBF buffer API bindings:

  • Bchg(), Bget(), Badd(), Bdel()
  • Field ID and type management
  • Buffer allocation and manipulation

server

Enables server-side bindings:

  • atmisrvnomain() - Main server entry point
  • tpsvrinit(), tpsvrdone() - Server lifecycle hooks
  • tpadvertise(), tpunadvertise() - Service advertisement

client

Enables client-side bindings:

  • tpinit(), tpterm() - Connection management
  • tpcall(), tpacall(), tpgetrply() - Service calls

derive

Enables #[derive(UbfStructDerive)] macro for automatic UBF serialization. Requires the endurox-derive crate.

Safety

Most functions in this crate are marked unsafe as they interact with C FFI and raw pointers. Safe wrappers can be found in higher-level crates built on top of endurox-sys.

Always ensure:

  • Buffers are properly allocated before use
  • tpinit() is called before any XATMI operations
  • Resources are freed with tpfree() and tpterm()
  • Error codes are checked after each operation

Error Handling

Use tperrno() and tpstrerror() to get error information:

use endurox_sys::*;

unsafe {
    if tpcall(...).is_err() {
        let errno = tperrno();
        let error = std::ffi::CStr::from_ptr(tpstrerror(errno))
            .to_string_lossy();
        eprintln!("Error: {}", error);
    }
}

Documentation

For complete API documentation, see docs.rs/endurox-sys.

For Enduro/X documentation, visit www.endurox.org/dokuwiki.

License

Licensed under the MIT license. See LICENSE for details.

Related Crates

Commit count: 0

cargo fmt