# -*- coding: utf-8 -*- | |
from ctypes import * | |
bccclt_dll = None | |
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" | |
] | |
def load_bccclt(): | |
global bccclt_dll | |
bccclt_dll = cdll.LoadLibrary('bccclt.dll') | |
load_bccclt() | |
class pyBccclt: | |
drtp_no = -1 | |
def setup(ip,port,xpack='cpack.dat',debug=0): | |
''' 初始化 ''' | |
global xpack_path | |
xpack_path = xpack | |
bccclt_dll.SetDebugSwitch( debug ) | |
r = bccclt_dll.BCCCLTInit(1) | |
if not r: | |
raise RuntimeError(u"初始化连接失败") | |
no = bccclt_dll.AddDrtpNode(ip,port) | |
pyBccclt.drtp_no = no | |
if pyBccclt.drtp_no < 0: | |
raise RuntimeError(u'初始化通讯平台连接失败') | |
setup = staticmethod(setup) | |
def __init__(self,mainfunc): | |
self.handle = bccclt_dll.NewXpackHandle( xpack_path ) | |
self.mainfunc = mainfunc | |
self.reset() | |
def get_errormsg(self): | |
return self.error_msg.value | |
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 | |
bccclt_dll.ResetPackHandle(self.handle) | |
def close(self): | |
if self.handle <> None: | |
bccclt_dll.DeleteXpackHandle( self.handle ) | |
self.handle = None | |
def callsvr(self,func,request,timeout = 1000): | |
self.reset() | |
self.timeout = timeout | |
for k,v in request.iteritems(): | |
if k not in cpack_fields: | |
raise ValueError(u"字段 %s 不存在" % k) | |
if isinstance(v,int): | |
bccclt_dll.SetIntFieldByName(self.handle,self.request_row,k,v) | |
elif isinstance(v,float): | |
bccclt_dll.SetDoubleFieldByName(self.handle,self.request_row,k,v) | |
elif isinstance(v,str): | |
bccclt_dll.SetStringFieldByName(self.handle,self.request_row,k,v) | |
else: | |
raise ValueError(u"字段 %s 数据类型错误" % k) | |
bccclt_dll.SetRequestType(self.handle,func) | |
#print "CallRequest %d:%d" % (self.mainfunc,func) | |
if not 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) | |
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 = bccclt_dll.GetRetCode(self.handle,byref(self.return_code)) | |
if not r: | |
raise RuntimeError(u'取返回码错误') | |
if self.get_retcode() <> 0: | |
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 bccclt_dll.HaveNextPack( self.handle ): | |
return False | |
elif not 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) | |
bccclt_dll.GetRecordCount(self.handle,byref(cnt)) | |
self.record_count = cnt.value | |
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 < 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 += chr(t1) | |
i += 2 | |
return 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 = 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': | |
v = create_string_buffer('\000' * 512) | |
r = bccclt_dll.GetStringFieldByName(self.handle,self.response_row,ctype_field,v,511) | |
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 = 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 = bccclt_dll.GetStringFieldByName(self.handle,self.response_row,ctype_field,v,1023) | |
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 | |