port over ctypeslib2

After many years without ctypeslib maintenance, there's finally a
ctypeslib2 for python3.x

Instead of the crude gcc2xml hack it uses libclang to generate python
directly from the C.

Change-Id: I9efd56623ebeabef4317356a05484a620a3a91cc
This commit is contained in:
Harald Welte 2024-03-16 20:28:41 +01:00
parent 2c38d1b1be
commit 79a26963cc
5 changed files with 619 additions and 1726 deletions

View File

@ -18,7 +18,7 @@ import logging as log
from fysom import Fysom
from mncc_sock import mncc_msg, mncc_number, mncc_rtp_msg, mncc_bridge_msg, mncc_bearer_cap
Uint32Array2 = mncc.uint32_t * 2
Uint32Array2 = ctypes.c_uint32 * 2
class GSM48:
class BCAP_SV(object):

6
mncc.h
View File

@ -127,7 +127,7 @@ struct gsm_mncc_bearer_cap {
int radio; /* Radio Channel Requirement */
int speech_ctm; /* CTM text telephony indication */
int speech_ver[8]; /* Speech version indication */
struct {
struct gsm_mncc_bearer_cap_data {
enum gsm48_bcap_ra rate_adaption;
enum gsm48_bcap_sig_access sig_access;
int async;
@ -185,7 +185,7 @@ struct gsm_mncc_cccap {
int pcp;
};
enum {
enum gsm_mncc_bcap {
GSM_MNCC_BCAP_SPEECH = 0,
GSM_MNCC_BCAP_UNR_DIG = 1,
GSM_MNCC_BCAP_AUDIO = 2,
@ -292,7 +292,7 @@ struct gsm_mncc {
struct gsm_mncc_facility facility;
struct gsm_mncc_cccap cccap;
struct gsm_mncc_ssversion ssversion;
struct {
struct gsm_mncc_clir {
int sup;
int inv;
} clir;

2271
mncc.py

File diff suppressed because it is too large Load Diff

View File

@ -17,7 +17,7 @@ import ctypes
class mncc_msg_common:
def send(self):
return buffer(self)[:]
return bytes(memoryview(self))
def receive(self, bytes):
fit = min(len(bytes), ctypes.sizeof(self))
ctypes.memmove(ctypes.addressof(self), bytes, fit)
@ -31,19 +31,19 @@ class mncc_msg_common:
mncc.GSM_TCHH_FRAME, mncc.GSM_TCHF_FRAME_EFR,
mncc.GSM_TCH_FRAME_AMR, mncc.GSM_BAD_FRAME)
class mncc_msg(mncc.gsm_mncc, mncc_msg_common):
class mncc_msg(mncc.struct_gsm_mncc, mncc_msg_common):
def __str__(self):
return 'mncc_msg(type=0x%04x, callref=%u, fields=0x%04x)' % (self.msg_type, self.callref, self.fields)
def __unicode__(self):
return u'mncc_msg(type=0x%04x, callref=%u, fields=0x%04x)' % (self.msg_type, self.callref, self.fields)
class mncc_hello_msg(mncc.gsm_mncc_hello, mncc_msg_common):
class mncc_hello_msg(mncc.struct_gsm_mncc_hello, mncc_msg_common):
def __str__(self):
return 'mncc_hello_msg(version=0x%04x)' % (self.version)
def __unicode__(self):
return u'mncc_hello_msg(version=0x%04x)' % (self.version)
class mncc_data_frame_msg(mncc.gsm_data_frame, mncc_msg_common):
class mncc_data_frame_msg(mncc.struct_gsm_data_frame, mncc_msg_common):
def __str__(self):
return 'mncc_data_frame(type=0x%04x, codec=%s, callref=%u)' \
% (self.msg_type, self.codec_str(), self.callref)
@ -65,20 +65,20 @@ class mncc_data_frame_msg(mncc.gsm_data_frame, mncc_msg_common):
else:
return "(???)"
class mncc_rtp_msg(mncc.gsm_mncc_rtp, mncc_msg_common):
class mncc_rtp_msg(mncc.struct_gsm_mncc_rtp, mncc_msg_common):
def __str__(self):
return 'mncc_rtp_msg(type=0x%04x, callref=%u, ip=%x, port=%u)' % (self.msg_type, self.callref, self.ip, self.port)
def __unicode__(self):
return u'mncc_rtp_msg(type=0x%04x, callref=%u, ip=%x, port=%u)' % (self.msg_type, self.callref, self.ip, self.port)
class mncc_bridge_msg(mncc.gsm_mncc_bridge, mncc_msg_common):
class mncc_bridge_msg(mncc.struct_gsm_mncc_bridge, mncc_msg_common):
def __str__(self):
return 'mncc_bridge_msg(%u, %u)' % (self.callref[0], self.callref[1])
def __unicode__(self):
return u'mncc_bridge_msg(%u, %u)' % (self.callref[0], self.callref[1])
def mncc_number(number, num_type = 0, num_plan = 0, num_present = 1, num_screen = 0):
return mncc.gsm_mncc_number(number = number, type = num_type,
return mncc.struct_gsm_mncc_number(number = number.encode('utf-8'), type = num_type,
plan = num_plan, present = num_present,
screen = num_screen)
@ -92,7 +92,7 @@ def mncc_bearer_cap(codecs_permitted):
index = index + 1
speech_types[index] = -1
return mncc.gsm_mncc_bearer_cap(coding = 0, speech_ctm=0, radio = 1, speech_ver = speech_types, transfer = 0, mode = 0)
return mncc.struct_gsm_mncc_bearer_cap(coding = 0, speech_ctm=0, radio = 1, speech_ver = speech_types, transfer = 0, mode = 0)
class MnccSocketBase(object):
def send(self, msg):
@ -142,12 +142,12 @@ class MnccSocket(MnccSocketBase):
'(0x%04x vs 0x%04x)\n' % (msg.version, mncc.MNCC_SOCK_VERSION))
# Match expected message sizes / offsets
if (msg.mncc_size < ctypes.sizeof(mncc.gsm_mncc) or
msg.data_frame_size != ctypes.sizeof(mncc.gsm_data_frame) or
msg.called_offset != mncc.gsm_mncc.called.offset or
msg.signal_offset != mncc.gsm_mncc.signal.offset or
msg.emergency_offset != mncc.gsm_mncc.emergency.offset or
msg.lchan_type_offset != mncc.gsm_mncc.lchan_type.offset):
if (msg.mncc_size < ctypes.sizeof(mncc.struct_gsm_mncc) or
msg.data_frame_size != ctypes.sizeof(mncc.struct_gsm_data_frame) or
msg.called_offset != mncc.struct_gsm_mncc.called.offset or
msg.signal_offset != mncc.struct_gsm_mncc.signal.offset or
msg.emergency_offset != mncc.struct_gsm_mncc.emergency.offset or
msg.lchan_type_offset != mncc.struct_gsm_mncc.lchan_type.offset):
raise AssertionError('MNCC message alignment mismatch\n')
log.info('Received %s' % msg)

View File

@ -1,38 +1,6 @@
#/bin/sh
echo This script requires that python-ctypeslib is installed on the system
echo Unfortunately, this package is long unmaintained and only available on Debian8
echo This script requires that python-ctypeslib2 is installed on the system
echo See https://github.com/trolldbois/ctypeslib
echo
# If your distro doesn't provide python-ctypeslib:
# svn co "https://svn.python.org/projects/ctypes/trunk/ctypeslib/"
# cd ctypeslib
# python2 ./setup.py install --prefix /tmp/out
# ln -s h2xml.py /tmp/out/bin/h2xml
# ln -s xml2py.py /tmp/out/bin/xml2py
# export PYTHONPATH="$PYTHONPATH:/tmp/out/lib/python2.7/site-packages"
# export PATH="$PATH:/tmp/out/bin/"
# ./regen-mncc-py.sh
# == Troubleshooting:
# * h2ml: Failing with tracebak OSError Not found:
# One may be missing gccxml. On arch, install gccxml-git from AUR.
# * h2xml failing due to missing gccxml_builtins.h:
# Create empty file /tmp/include/gccxml_builtins.h and pass "-I /tmp/include/" to h2xml.
# * Missing __builtin_bswap16/32/64:
# Copy from /usr/include/bits/byteswap.h defines __bswap_constant_16/32/64 to
# either start of mncc.h itself or /tmp/include/gccxml_builtins.h, and rename
# them as __builtin_bswap16/32/64.
if [ ! -x `which h2xml` ]; then
echo No h2xml executable found - python-ctypeslib not installed?
exit 1
fi
if [ ! -x `which xml2py` ]; then
echo No xml2py executable found - python-ctypeslib not installed?
exit 1
fi
set -xe
cp ./mncc.h /tmp/mncc.h
h2xml -I /tmp/include/ ./mncc.h -c -o mncc.xml
xml2py mncc.xml -k dest -v -o mncc.py
clang2py -k ems -o mncc.py mncc.h