#!/usr/bin/python | |
# -*- coding: utf-8 -*- | |
from ctypes import * | |
xpack_path = 'cpack.dat' | |
cpack_fields = [ | |
"scust_no", | |
"scust_no2", | |
"sholder_ac_no", | |
"sholder_ac_no2", | |
"sholder_type", | |
"sholder_type2", | |
"sname", | |
"sname2", | |
"sall_name", | |
"smarket_code", | |
"smarket_code2", | |
"sdate0", | |
"sdate1", | |
"sdate2", | |
"sdate3", | |
"stime0", | |
"stime1", | |
"stime2", | |
"stime3", | |
"lvol0", | |
"lvol1", | |
"lvol2", | |
"lvol3", | |
"lvol4", | |
"lvol5", | |
"lvol6", | |
"lvol7", | |
"lvol8", | |
"lvol9", | |
"lvol10", | |
"lvol11", | |
"lvol12", | |
"damt0", | |
"damt1", | |
"damt2", | |
"damt3", | |
"damt4", | |
"damt5", | |
"damt6", | |
"damt7", | |
"damt8", | |
"damt9", | |
"damt10", | |
"damt11", | |
"damt12", | |
"damt13", | |
"damt14", | |
"damt15", | |
"damt16", | |
"damt17", | |
"damt18", | |
"damt19", | |
"damt20", | |
"damt21", | |
"damt22", | |
"damt23", | |
"damt24", | |
"damt25", | |
"damt26", | |
"damt27", | |
"damt28", | |
"damt29", | |
"damt30", | |
"damt31", | |
"damt32", | |
"damt33", | |
"sstock_code", | |
"sstock_code2", | |
"scust_type", | |
"scust_type2", | |
"sstat_type", | |
"sstat_type2", | |
"sroom_no", | |
"sroom_no2", | |
"sopen_emp", | |
"sclose_emp", | |
"schange_emp", | |
"scheck_emp", | |
"semp", | |
"snation_code", | |
"lcert_code", | |
"stx_pwd", | |
"stx_pwd2", | |
"swithdraw_pwd", | |
"swithdraw_pwd2", | |
"semp_pwd", | |
"semp_pwd2", | |
"sbank_pwd", | |
"sbank_pwd2", | |
"scust_auth", | |
"scust_auth2", | |
"scust_limit", | |
"scust_limit2", | |
"lsafe_level", | |
"lsafe_level2", | |
"spost_code", | |
"spost_code2", | |
"sphone", | |
"sphone2", | |
"sphone3", | |
"spager", | |
"semail", | |
"semail2", | |
"snote", | |
"snote2", | |
"scert_no", | |
"scert_no2", | |
"scert_addr", | |
"sstatus0", | |
"sstatus1", | |
"sstatus2", | |
"sstatus3", | |
"sstatus4", | |
"lwithdraw_flag", | |
"saddr", | |
"saddr2", | |
"sserial0", | |
"sserial1", | |
"sserial2", | |
"sserial3", | |
"sserial4", | |
"scurrency_type", | |
"scurrency_type2", | |
"sbranch_code0", | |
"sbranch_code1", | |
"sbranch_code2", | |
"usset0", | |
"usset1", | |
"usset2", | |
"usset3", | |
"usset4", | |
"usset5", | |
"usset6", | |
"sstation0", | |
"sstation1", | |
"sbank_acc", | |
"sbank_acc2", | |
"lbank_acc_type", | |
"lbank_acc_type2", | |
"smain_flag", | |
"smain_flag2", | |
"sbank_code", | |
"sbank_code2", | |
"semp_no", | |
"semp_no2", | |
"drate0", | |
"drate1", | |
"lserial0", | |
"lserial1", | |
"sbankname", | |
"sbankname2", | |
"scard0", | |
"scard1", | |
"sorder0", | |
"sorder1", | |
"sorder2", | |
"scusttypes", | |
"ssectypes", | |
"vsmess", | |
"vsvarstr0", | |
"vsvarstr1", | |
"vsvarstr2", | |
"vsvarstr3" | |
] | |
class pyBccclt: | |
drtp_no = -1 | |
bccclt_dll = None | |
@staticmethod | |
def load_bccclt(): | |
pyBccclt.bccclt_dll = cdll.LoadLibrary('bccclt.dll') | |
@staticmethod | |
def setup(ip, port, xpack='cpack.dat', debug=0): | |
''' 初始化 ''' | |
if not pyBccclt.bccclt_dll: | |
pyBccclt.load_bccclt() | |
global xpack_path | |
xpack_path = xpack | |
pyBccclt.bccclt_dll.SetDebugSwitch(debug) | |
r = pyBccclt.bccclt_dll.BCCCLTInit(1) | |
if not r: | |
raise RuntimeError(u"初始化连接失败") | |
no = pyBccclt.bccclt_dll.AddDrtpNode(ip, port) | |
pyBccclt.drtp_no = no | |
if pyBccclt.drtp_no < 0: | |
raise RuntimeError(u'初始化通讯平台连接失败') | |
def __init__(self, mainfunc): | |
self.handle = pyBccclt.bccclt_dll.NewXpackHandle(xpack_path) | |
if isinstance(mainfunc, str) or isinstance(mainfunc, unicode): | |
self.mainfunc = int(mainfunc) | |
else: | |
self.mainfunc = mainfunc | |
self.reset() | |
def get_errormsg(self): | |
return self.error_msg.value.decode('gbk') | |
def reset(self): | |
self.request_row = 0 | |
self.error_code = c_int(0) | |
self.error_msg = create_string_buffer('\000' * 1024) | |
self.return_code = c_int(0) | |
self.record_count = 0 | |
self.record = None | |
self.timeout = 5000 | |
self.response_row = 0 | |
self.raw_resp = None | |
pyBccclt.bccclt_dll.ResetPackHandle(self.handle) | |
def close(self): | |
if self.handle != None: | |
pyBccclt.bccclt_dll.DeleteXpackHandle(self.handle) | |
self.handle = None | |
def callsvr(self, func, request, timeout=1000): | |
self.reset() | |
self.timeout = timeout | |
if request: | |
for k, v in request.iteritems(): | |
if k not in cpack_fields: | |
raise ValueError(u"字段 %s 不存在" % k) | |
if isinstance(v, int): | |
pyBccclt.bccclt_dll.SetIntFieldByName(self.handle, self.request_row, k, v) | |
elif isinstance(v, float): | |
pyBccclt.bccclt_dll.SetDoubleFieldByName(self.handle, self.request_row, k, v) | |
elif isinstance(v, str): | |
pyBccclt.bccclt_dll.SetStringFieldByName(self.handle, self.request_row, k, v) | |
else: | |
raise ValueError(u"字段 %s 数据类型错误" % k) | |
pyBccclt.bccclt_dll.SetRequestType(self.handle, func) | |
#print "CallRequest %d:%d" % (self.mainfunc,func) | |
if not pyBccclt.bccclt_dll.CallRequest(self.handle, pyBccclt.drtp_no, 0, | |
self.mainfunc, timeout, byref(self.error_code), self.error_msg): | |
#print "CallRequest error " | |
return False | |
self.get_return_error() | |
cnt = c_int(0) | |
pyBccclt.bccclt_dll.GetRecordCount(self.handle, byref(cnt)) | |
self.record_count = cnt.value | |
return True | |
def get_retcode(self): | |
return self.return_code.value | |
def get_return_error(self): | |
r = pyBccclt.bccclt_dll.GetRetCode(self.handle, byref(self.return_code)) | |
if not r: | |
raise RuntimeError(u'取返回码错误') | |
if self.get_retcode() != 0: | |
pyBccclt.bccclt_dll.GetStringFieldByName(self.handle, 0, "vsmess", self.error_msg) | |
return self.return_code.value | |
def has_more_record(self): | |
#print "resp:%d, record: %d" % (self.response_row , self.record_count) | |
if self.response_row < self.record_count: | |
return True | |
elif not pyBccclt.bccclt_dll.HaveNextPack(self.handle): | |
return False | |
elif not pyBccclt.bccclt_dll.CallNext(self.handle, self.timeout, | |
byref(self.error_code), self.error_msg): | |
raise RuntimeError(u'获取后续数据包异常') | |
else: | |
self.response_row = 0 | |
self.record_count = 0 | |
self.get_return_error() | |
if self.get_retcode() != 0: | |
raise RuntimeError(u'取后续数据返回错误,ret=%d' % self.get_retcode()) | |
cnt = c_int(0) | |
pyBccclt.bccclt_dll.GetRecordCount(self.handle, byref(cnt)) | |
self.record_count = cnt.value | |
# print "next count: %d" % self.record_count | |
if self.response_row < self.record_count: | |
return True | |
return False | |
def convert_ascii(self, data): | |
i = 0 | |
datalen = len(data) | |
result = [] | |
while i < datalen: | |
t = data[i: i + 2] | |
t1 = int(t, 16) & 0xFF | |
if t1 == 0: | |
break | |
if (t1 < ord('0') or t1 > ord('9')) and (t1 < ord('A') or t1 > ord('F')): | |
raise ValueError("Value is non-hexdicimal %s:%d" % (chr(t1), t1)) | |
result.append(chr(t1)) | |
i += 2 | |
return "".join(result) | |
def next_record(self, fields): | |
if self.response_row >= self.record_count: | |
raise ValueError(u'无可用记录') | |
self.record = {} | |
for f in fields: | |
#print "获取字段 ",f | |
if f not in cpack_fields: | |
raise ValueError(u"字段 %s 不存在" % f) | |
ctype_field = create_string_buffer(f) | |
if f[0] == 'l': | |
v = c_int(0) | |
r = pyBccclt.bccclt_dll.GetIntFieldByName(self.handle, self.response_row, | |
ctype_field, byref(v)) | |
if not r: | |
raise ValueError(u"字段 %s 未返回" % f) | |
self.record[f] = v.value | |
elif f[0] == 's' or f[0] == 'v': | |
v = create_string_buffer('\000' * 512) | |
r = pyBccclt.bccclt_dll.GetStringFieldByName(self.handle, self.response_row, ctype_field, v) | |
if not r: | |
raise ValueError(u"字段 %s 未返回" % f) | |
#print "%s: %s" % (f,v.value) | |
self.record[f] = v.value | |
elif f[0] == 'd': | |
v = c_double(0.0) | |
r = pyBccclt.bccclt_dll.GetDoubleFieldByName(self.handle, self.response_row, | |
ctype_field, byref(v)) | |
if not r: | |
raise ValueError(u"字段 %s 未返回" % f) | |
self.record[f] = v.value | |
elif f[0] == 'u': | |
v = create_string_buffer('\000' * 1024) | |
r = pyBccclt.bccclt_dll.GetStringFieldByName(self.handle, self.response_row, | |
ctype_field, v) | |
if not r: | |
raise ValueError(u"字段 %s 未返回" % f) | |
data = v.value | |
data = data[2:] | |
data = self.convert_ascii(data) | |
self.record[f] = data | |
else: | |
raise ValueError(u'字段类型错误 %s' % f) | |
self.response_row += 1 | |
#print "fetch one record , " ,self.record | |
return self.record | |
def fetch_record(self, fields): | |
while self.has_more_record(): | |
ret = self.next_record(fields) | |
yield ret | |
def send_raw_data(self, data, requesttype, timeout): | |
if isinstance(data, unicode): | |
data = data.encode('gbk') | |
pyBccclt.bccclt_dll.SetRawRecord(self.handle, 0, data, len(data)) | |
pyBccclt.bccclt_dll.SetRequestType(self.handle, requesttype) | |
r = pyBccclt.bccclt_dll.CallRequest(self.handle, pyBccclt.drtp_no, 0, | |
self.mainfunc, timeout, byref(self.error_code), self.error_msg) | |
if not r: | |
return False | |
if self.raw_resp is None: | |
self.raw_resp = create_string_buffer(8196) | |
else: | |
memset(self.raw_resp, 0, sizeof(self.raw_resp)) | |
r = pyBccclt.bccclt_dll.GetRawRecord(self.handle, 0, self.raw_resp, 8196) | |
if not r: | |
return False | |
return True | |
def raw_data(self): | |
if self.raw_resp is None: | |
raise ValueError(u"response is None") | |
return self.raw_resp.value |