Pytibrv
TIBRV API for Python
Install / Use
/learn @arienchen/PytibrvREADME
PYTIBRV
PYTIBRV is a Python wrapper for TIBRV/C API
TIBCO Rendezvous® (aka TIBRV) is copyright of TIBCO
Table of Contents
Background
PYTIBRV use ctypes to call TIBRV/C API, It is not a Pyhton Extension.
So, it is unnecessary to build/compile any C source for deployment.
PYTIBRV contains
-
Python API (aka PYTIBRV/API)
Most of TIBRV/C API are ported to PYTIBRV/API.
Before that, you must be familer with TIBRV/C API.
Naming convention istibrv(lowercase), such astibrv_status, tibrvMsg, tibrvMsg_Create -
Python Object Model (aka PYTIBRV/Object) PYTIBRV provide object model, like as TIBRV/Java, which package TIBRV/C API to components.
Naming convention isTibrv(capital), such asTibrvStatus, TibrvMsg, TibrvListener
Install
Copy pytibr/pytibrv into your Python packages directory,
for example: $HOME/my_lib/
$HOME/my_lib/pytibrv/
__init__,py
api.py
...
I am still working on setup.py
Then, add $HOME/my_lib to PYTHONPATH
export PYTHONPATH=$HOME/my_lib
run python console to test
from pytibrv.api import *
status = tibrv_Open()
Usage
PYTIBRV also rewrite TIBRV/C Examples to Python. Please refer to examples for detail.
-
tibrvsend PYTIBRV/Object
Send Out a reliable RV message -
tibrvlisten PYTIBRV/Object
Listen and display content of RV message for specific subject -
timer PYTIBRV/Object
Demostrate TIBRV Timer / Callback / Closure -
tibrvfttime PYTIBRV/Object
RVFT API, program support active/standby AUTO-FAILOVER, to send out RV message within timestamp. -
tibrvftmon PYTIBRV/Object
RVFT API, program to monitor RVFT Members activities -
tibrvcmsend PYTIBRV/Object
Send out a certified RV message -
tibrvcmlisten PYTIBRV/Object
Listen and display content of certified RV message for multiple subjects -
tibrvdqlisten PYTIBRV/Object
RVDQ API, program support LOAD-SHARING, to listen and display RV message for specific subjects.
TIBRV/C API
All TIBRV/C API return tibrv_status to indicate the calling status.
It use C POINTER(Call By Reference) to return created object handle.
// C in tibrv/msg.h
tibrv_status tibrvMsg_Create(tibrvMsg * msg)
// in your code
tibrv_status status;
tibrvMsg msg;
tibrv_i32 amt = 12345;
status = tibrvMsg_Create(&msg)
if (TIBRV_OK != status) {
// error handling
}
status = tibrvMsg_UpdateI32(msg, "AMOUNT", amt);
...
Python
Python are all objects, there is no 'native' data type, like as C int/double.
>>> x = int(123)
>>> type(x)
<class 'int'>
>>>
And, Python is all 'Call By Refence',
more precisely, Python is 'Call By Reference of Object'
Unfortunately, Python 'Call By Reference' is immutable for most case,
you CAN'T return a new object like as C POINTER.
# Python
def change(x):
x = 'ABC'
...
y = '123'
change(y)
print(y) # y is still '123'
When Python runing x = 'ABC' in change()
It assign local variable x to a new string object reference.
Actually, local variable x would be GC when change() returned
In other way, Python support return as tuple.
Rewrite TIBRV/C tibrvMsg_Create() to PYTIBRV/API
# PYTIBRV/API
def tibrvMsg_Create() -> (tibrv_status, tibrvMsg):
# calling C API by ctypes
msg = ctypes.c_void_p()
status = _rvlib.tibrvMsg_Create(ctypes.byref(msg))
return status, msg.value
...
status, msg = tibrvMsg_Create() # return as tuple []
if status != TIBRV_OK:
# error handling
status = tibrvMsg_UpdateI32(msg, 'AMOUNT', amt)
Callback
In TIBRV/C, callback is declared as
typedef void (*tibrvEventCallback) (
tibrvEvent event,
tibrvMsg message,
void* closure
);
...
void my_callback(tibrvEvent event, tibrvMsg message, void * closure) {
// do what you need
...
}
...
status = tibrvEvent_CreateListener(&event, que, my_callback, tx, "_RV.>", NULL);
In Python, ALL is dynamic binding and no function typedef.
# Python
def my_callback(event: int, messgae: int, closure: object):
# do what you need
status, sz = tibrvMsg_GetString(message, 'DATA')
...
status, listener = tibrvEvent_CreateListener(que, my_callback, tx, '_RV.>', None)
Python3.6 support NewType and Callable from typing
# Python
from typing import NewType, Callable
tibrv_status = NewType('tibrv_status', int) # int
tibrvId = NewType('tibrvId', int) # int
tibrvMsg = NewType('tibrvMsg', int) # c_void_p
tibrvEvent = NewType('tibrvEvent', int) # tibrvId
tibrvDispatchable = NewType('tibrvDispatchable', int) # tibrvId
tibrvQueue = NewType('tibrvQueue', int) # tibrvId
...
tibrvEventCallback = Callable[[tibrvEvent, tibrvMsg, object], None]
def tibrvEvent_CreateListener(que: tibrvQueue, callback: tibrvEventCallback, tx: tibrvTransport,
subj: str, closure: object) -> tibrv_status:
...
def my_callback(event: tibrvEvent, messgae: tibrvMsg, closure: object):
# do what you need
status, sz = tibrvMsg_GetString(message, 'DATA')
...
status, listener = tibrvEvent_CreateListener(que, my_callback, tx, '_RV.>', None)
Callback must be declared in module level,
You CAN'T assign a class function(method) for callback.
All Python class functions are pre-defined 'self' as 1'st parameter.
# in Python
class MyApp:
def my_callback(self, event, message, closure):
# THIS IS NOT WORK
Suggest to code as
# in Python, use closure for your own reference.
def my_callback(event, message, closure):
my_app = closure
if my_app.flags == 0:
...
class MyApp:
def __init__(self):
self.flags = 0
...
def init_rv(slef):
# pass self as closure, to be accessed in callback
status, listener = tibrvEvent_CreateListener(que, my_callback, tx, '_RV.>', self)
Please refer examples/api/timer.py or examples/api/tibrvlisten.py for more detail.
I rewrite callback as Python Class, it is more strait forward.
Please refer examples/python/timer.py
or examples/python/tibrvlisten.py for more detail.
Data Types
- Python only provide bool, int, gloat, str as native data types,
Not likely as C, TIBRV/C support for I8, U8, I16, ..., I64, U64, F32, F64
Python ctypes support for all C native data type: I8 ... F64
BUT ctypes DOES NOT PERFORM OVERFLOW CHECKING
for exexample:
# In Python
# 0xFFF = int(4095)
status = tibrvMsg_UpdateI8(msg, 'I8', 0xFFF) # -> I8 = -1
status = tibrvMsg_UpdateU8(msg, 'U8', 0xFFF) # -> U8 = 255
- TIBRV/C Object Handle
TIBRV/C declaretibrvIdastibrv_u32(unsigned int)
tibrvEvent, tibrvTransport, tibrvQueue, tibrvDispatcherare all derived fromtibrvId
tibrvMsgis actually a pointer to struct
In PYTIBRV/API, they are all declared as 'int'
Exception
TIBRV/C API is 'exceptionless', beecause there is no Exception in C.
You only need to check the returned code after calling.
PYTIBRV/API is the same as TIBRV/C. You only need to check the returned code.
PYTIBRV/Object is like as PYTIBRV/API mostly.
You could check tibrv_status if there is a returned code.
Or, you could access obj.error() to get last TibrvError. (like as C errno)
# PYTIBRV/Object
tx = TibrvTx()
status = tx.create(None, None, None)
# check return code
if status != TIBRV_OK:
# erro handling
# there is no return code for property
tx.description = 'TEST'
if tx.error() is not None:
# error handling
print('ERROR', tx.error().code(), tx.error().text())
If you prefer Exception(try/except) Handling,
you could set TibrvStatus.exception(True).
This would trigger TibrvError when tibrv_status is not TIBRV_OK.
# PYTIBRV/Object
# enable exception handling
TibrvStatus.exception(True)
try:
tx = TibrvTx()
tx.create(None, None, None)
tx.description = 'TEST'
except TibrvErrr as er:
# error handling
print('ERROR', er.code(), er.text())
API
TIBRV
TIBRV/C | PYTIBRV/API | PYTIBRV/Object
--- | --- | ---
tibrv_Open() | tibrv_Open() | Tibrv.open()
tibrv_Close() | tibrv_Close() | Tirv.close()
tibrv_Version() | tibrv_Version() | Tibrv.version()
# PYTIBRV/API
status = tibrv_Open()
if status != TIBRV_OK:
print('ERROR', status, tibrvStatus_GetText(status))
sys.exit(-1)
#PYTIBRV/Object
status = Tibrv.open()
if status != TIBRV_OK:
print('ERROR', status, TibrvStatus.text(status))
sys.
