Crate kdb_c_api

Source
Expand description

!!Notice!! This crate was migrated to kdbplus which has IPC module as well.

Rust crate mirroring the C API header file (k.h) for kdb+. The expected usage is to build a shared library for kdb+ in Rust.

In order to avoid writing too large unsafe block leading to poor optimization, most of native C API functions were provided with a wrapper funtion with a bit of ergonomic safety and with intuitive implementation as a trait method. The only exceptions are knk and k which are using elipsis (...) as its argument. These functions are provided under native namespace with the other C API functions.

§Note

  • This library is for kdb+ version >= 3.0.
  • Meangless C macros are excluded but accessors of an underlying array like kC, kJ, kK etc. are provided in Rust way.

§Examples

The examples of using C API wrapper are included in c_api_examples folder. The examples are mirroring the examples in the document of kdb_c_api library and the functions are also used for simple tests of the library. The test is conducted in the test.q under tests/ by loading the functions defined in a shared library built from the examples.

Here are some examples:

§C API Style

use kdb_c_api::*;
use kdb_c_api::native::*;
 
#[no_mangle]
pub extern "C" fn create_symbol_list(_: K) -> K{
  unsafe{
    let mut list=ktn(qtype::SYMBOL as i32, 0);
    js(&mut list, ss(str_to_S!("Abraham")));
    js(&mut list, ss(str_to_S!("Isaac")));
    js(&mut list, ss(str_to_S!("Jacob")));
    js(&mut list, sn(str_to_S!("Josephine"), 6));
    list
  }
}
  
#[no_mangle]
pub extern "C" fn catchy(func: K, args: K) -> K{
  unsafe{
    let result=ee(dot(func, args));
    if (*result).qtype == qtype::ERROR{
      println!("error: {}", S_to_str((*result).value.symbol));
      // Decrement reference count of the error object
      r0(result);
      KNULL
    }
    else{
      result
    }
  }
}
 
#[no_mangle]
pub extern "C" fn dictionary_list_to_table() -> K{
  unsafe{
    let dicts=knk(3);
    let dicts_slice=dicts.as_mut_slice::<K>();
    for i in 0..3{
      let keys=ktn(qtype::SYMBOL as i32, 2);
      let keys_slice=keys.as_mut_slice::<S>();
      keys_slice[0]=ss(str_to_S!("a"));
      keys_slice[1]=ss(str_to_S!("b"));
      let values=ktn(qtype::INT as i32, 2);
      values.as_mut_slice::<I>()[0..2].copy_from_slice(&[i*10, i*100]);
      dicts_slice[i as usize]=xD(keys, values);
    }
    // Format list of dictionary as a table.
    // ([] a: 0 10 20i; b: 0 100 200i)
    k(0, str_to_S!("{[dicts] -1 _ dicts, (::)}"), dicts, KNULL)
  } 
}

q can use these functions like this:

q)summon:`libc_api_examples 2: (`create_symbol_list; 1)
q)summon[]
`Abraham`Isaac`Jacob`Joseph
q)`Abraham`Isaac`Jacob`Joseph ~ summon[]
q)catchy: `libc_api_examples 2: (`catchy; 2);
q)catchy[$; ("J"; "42")]
42
q)catchy[+; (1; `a)]
error: type
q)unfortunate_fact: `libc_api_examples 2: (`dictionary_list_to_table; 1);
q)unfortunate_fact[]
a  b  
------
0  0  
10 100
20 200

§Rust Style

The examples below are written without unsafe code. You can see how comfortably breathing are the wrapped functions in the code.

use kdb_c_api::*;
 
#[no_mangle]
pub extern "C" fn create_symbol_list2(_: K) -> K{
  let mut list=new_simple_list(qtype::SYMBOL, 0);
  list.push_symbol("Abraham").unwrap();
  list.push_symbol("Isaac").unwrap();
  list.push_symbol("Jacob").unwrap();
  list.push_symbol_n("Josephine", 6).unwrap();
  list
}
 
#[no_mangle]
fn no_panick(func: K, args: K) -> K{
  let result=error_to_string(apply(func, args));
  if result.get_type() == qtype::ERROR{
    println!("FYI: {}", result.get_symbol().unwrap());
    // Decrement reference count of the error object which is no longer used.
    decrement_reference_count(result);
    KNULL
  }
  else{
    println!("success!");
    result
  }
}
 
#[no_mangle]
pub extern "C" fn create_table2(_: K) -> K{
  // Build keys
  let keys=new_simple_list(qtype::SYMBOL, 2);
  let keys_slice=keys.as_mut_slice::<S>();
  keys_slice[0]=internalize(str_to_S!("time"));
  keys_slice[1]=internalize_n(str_to_S!("temperature_and_humidity"), 11);
 
  // Build values
  let values=new_simple_list(qtype::COMPOUND, 2);
  let time=new_simple_list(qtype::TIMESTAMP, 3);
  // 2003.10.10D02:24:19.167018272 2006.05.24D06:16:49.419710368 2008.08.12D23:12:24.018691392
  time.as_mut_slice::<J>().copy_from_slice(&[119067859167018272_i64, 201766609419710368, 271897944018691392]);
  let temperature=new_simple_list(qtype::FLOAT, 3);
  temperature.as_mut_slice::<F>().copy_from_slice(&[22.1_f64, 24.7, 30.5]);
  values.as_mut_slice::<K>().copy_from_slice(&[time, temperature]);
   
  flip(new_dictionary(keys, values))
}

And q code is here:

q)summon:`libc_api_examples 2: (`create_symbol_list2; 1)
q)summon[]
`Abraham`Isaac`Jacob`Joseph
q)chill: `libc_api_examples 2: (`no_panick; 2);
q)chill[$; ("J"; "42")]
success!
42
q)chill[+; (1; `a)]
FYI: type
q)climate_change: libc_api_examples 2: (`create_table2; 1);
q)climate_change[]
time                          temperature
-----------------------------------------
2003.10.10D02:24:19.167018272 22.1       
2006.05.24D06:16:49.419710368 24.7       
2008.08.12D23:12:24.018691392 30.5  

Modules§

native
This module exposes bare C API functions. As most of them are provided with a “safe” wrapper function with an intuitive name and intuitive implementation for Rust, there is no gain to darely use these functions.
qattribute
This module provides a list of q attributes. The motivation to contain them in a module is to tie them up as related items rather than scattered values. Hence user should use these indicators with qattribute:: prefix, e.g., qattribute::UNIQUE.
qtype
This module provides a list of q types. The motivation to contain them in a module is to tie them up as related items rather than scattered values. Hence user should use these indicators with qtype:: prefix, e.g., qtype::BOOL.

Macros§

str_to_S
Convert &str to S (null-terminated character array).

Structs§

U
Struct representing 16-bytes GUID.
k0
Underlying struct of K object.
k0_list_info
Underlying list value of q object.

Constants§

KNULL
K nullptr. This value is used as general null returned value ((::)).

Traits§

KUtility

Functions§

S_to_str
Convert S to &str. This function is intended to convert symbol type (null-terminated char-array) to str.
apply
Apply a function to q list object .[func; args].
days_to_ymd
Convert the number of days from 2000.01.01 to a number expressed as yyyymmdd.
decrement_reference_count
Decrement reference count of the q object. The decrement must be done when k function gets an error object whose type is qtype::ERROR and when you created an object but do not intend to return it to q side. See details on the reference page.
destroy_socket
Remove callback from the associated kdb+ socket and call kclose. Return null if the socket is invalid or not the one which had been registered by sd1.
destroy_socket_if
Remove callback from the associated kdb+ socket and call kclose if the given condition is satisfied. Return null if the socket is invalid or not the one which had been registered by sd1.
drop_q_object
Drop Rust object inside q. Passed as the first element of a foreign object.
enkey
Constructor of q keyed table object.
error_to_string
Convert an error object into usual K object which has the error string in the field s.
flip
Constructor of q table object from a q dictionary object.
increment_reference_count
Increment reference count of the q object. Increment must be done when you passed arguments to Rust function and intends to return it to q side or when you pass some K objects to k function and intend to use the argument after the call. See details on the reference page.
internalize
Intern a null-terminated char array. Returns an interned char array and should be used to add char array to a symbol vector.
internalize_n
Intern n chars from a char array. Returns an interned char array and should be used to add char array to a symbol vector.
load_as_q_function
Load C function as a q function (K object).
new_bool
Constructor of q bool object. Relabeling of kb.
new_byte
Constructor of q byte object. Relabeling of kg.
new_char
Constructor of q char object. Relabeling of kc.
new_date
Constructor of q date object. Relabeling of kd.
new_datetime
Constructor of q datetime object from the number of days since kdb+ epoch (2000.01.01). Relabeling of kz.
new_dictionary
Constructor of q dictionary object.
new_error
Constructor of q error. The input must be null-terminated.
new_error_os
Similar to new_error but this function appends a system-error message to string S before passing it to internal krr. The input must be null-terminated.
new_float
Constructor of q float object. Relabeling of kf.
new_guid
Constructor of q GUID object. Relabeling of ku.
new_int
Constructor of q int object. Relabeling of ki.
new_long
Constructor of q long object. Relabeling of kj.
new_minute
Create a month object. This is a complememtal constructor of missing minute type.
new_month
Create a month object from the number of months since kdb+ epoch (2000.01.01). This is a complememtal constructor of missing month type.
new_real
Constructor of q real object. Relabeling of ke.
new_second
Create a month object. This is a complememtal constructor of missing second type.
new_short
Constructor of q short object. Relabeling of kh.
new_simple_list
Constructor of q simple list.
new_string
Constructor of q string object.
new_string_n
Constructor if q string object with a fixed length.
new_symbol
Constructor of q symbol object. Relabeling of ks.
new_time
Constructor of q time object. Relabeling of kt.
new_timespan
Constructor of q timespan object from nanoseconds. Relabeling of ktj.
new_timestamp
Constructor of q timestamp from elapsed time in nanoseconds since kdb+ epoch (2000.01.01). Relabeling of ktj.
null_terminated_str_to_S
Convert null-terminated &str to S.
null_terminated_str_to_const_S
Convert null terminated &str into const_S. Expected usage is to build a q error object with krr.
pin_symbol
Lock a location of internalized symbol in remote threads. Returns the previously set value.
register_callback
Register callback to the associated kdb+ socket.
unkey
Constructor of simple q table object from a q keyed table object.
unpin_symbol
Unlock a location of internalized symbol in remote threads.
ymd_to_days
Convert ymd to the number of days from 2000.01.01.

Type Aliases§

C
char in C. Also used to access char of q.
E
f32 in C. Also used to access real of q.
F
f64 in C. Also used to access float and datetime of q.
G
unsigned char in C. Also used to access byte of q.
H
i16 in C. Also used to access short of q.
I
i32 in C. Also used to access int and compatible types (month, date, minute, second and time) of q.
J
i64 in C. Also used to access long and compatible types (timestamp and timespan) of q.
K
Struct representing q object.
S
char* in C. Also used to access symbol of q.
V
void in C.
const_S
const char* in C.

Unions§

k0_inner
Underlying atom value of q object.