SkillAgentSearch skills...

Pytibrv

TIBRV API for Python

Install / Use

/learn @arienchen/Pytibrv
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

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 is tibrv (lowercase), such as tibrv_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 is Tibrv (capital), such as TibrvStatus, 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.

Examples:

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

  1. 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 
  1. TIBRV/C Object Handle
    TIBRV/C declare tibrvId as tibrv_u32(unsigned int)
    tibrvEvent, tibrvTransport, tibrvQueue, tibrvDispatcher are all derived from tibrvId
    tibrvMsg is 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.
View on GitHub
GitHub Stars17
CategoryDevelopment
Updated11mo ago
Forks9

Languages

Python

Security Score

87/100

Audited on May 1, 2025

No findings