macro_rules! ci_t { ($tptoken: expr, $err_buffer: expr, $routine: expr $(, $args: expr)* $(,)?) => { ... }; }
Expand description
Make an FFI call to M.
ci_t
is equivalent to a variadic function with the following signature:
ⓘ
unsafe fn ci_t(tptoken: u64, err_buffer: Vec<u8>, routine: &CStr, ...) -> YDBResult<Vec<u8>>;
However, since Rust does not allow implementing variadic functions, it is a macro instead.
Safety
Each argument passed (after routine
) must correspond to the appropriate argument expected by routine
.
If routine
returns a value, the first argument must be a pointer to an out parameter in which to store the value.
All arguments must be representable as C types.
See also
- C to M FFI
- The M documentation on call-ins
cip_t!
, which allows caching theroutine
lookup, making future calls faster.
Example
Call the M routine described by HelloWorld1
in the call-in table.
See also examples/m-ffi/helloworld1.m
and examples/m-ffi/calltab.ci
.
use std::env;
use std::ffi::CString;
use std::os::raw::c_char;
use yottadb::{craw, ci_t, TpToken};
env::set_var("ydb_routines", "examples/m-ffi");
env::set_var("ydb_ci", "examples/m-ffi/calltab.ci");
let mut buf = Vec::<u8>::with_capacity(100);
let mut msg = craw::ydb_string_t { length: buf.capacity() as u64, address: buf.as_mut_ptr() as *mut c_char };
let routine = CString::new("HelloWorld1").unwrap();
unsafe {
ci_t!(TpToken::default(), Vec::new(), &routine, &mut msg as *mut _).unwrap();
buf.set_len(msg.length as usize);
}
assert_eq!(&buf, b"entry called");