总体目标的实现,首先通过python将sra文件编译成exe,Popen启动exe,调用写好的动态库文件函数,调用test.py中的代码。
先看一下实现的效果,testHello.py的代码
from PyPB import RUN,messagebox
def main():
messagebox("提示","你好,PB!")
RUN(__name__,__file__,main)
那我们是如何实现,在python中调用pb的messagebox的呢,这里就必须要用systemlibray了。基础部分就不介绍了,深入了解,百度哈。还有一个基础就是需要将python34源码编译成dll,我们把pbvm**.dll的handle注入到sys.pbvm中,程序启动时的_obThis等注入到sys.pb_app中。通过ctypes获取到对应的值
__obThis = ctypes.c_void_p ( sys.pb_app[0] )
__pGroup = ctypes.c_void_p ( sys.pb_app[1] )
__appinst = ctypes.c_void_p ( sys.pb_app[2] )
pbvm = ctypes.WinDLL("pbvm", handle = sys.pbvm)
定义OB_DATA,OB_DATA_INFO,RT_CALL_INFO,OB_CLASS_HNDL等结构体对象。
OB_CONST_REF =ctypes.c_ulong
class OB_VALUE(ctypes.Union):
_pack_ = 1
_fields_ = [
('int_val', ctypes.c_short), # SHORT int_val; // Integer value
('fl_val', ctypes.c_float), # FLOAT fl_val; // Float value
('pchar', ctypes.c_char_p),
('ptr', ctypes.c_void_p), # PVOID ptr; // Ptr to value
('const_ref', OB_CONST_REF), # OB_CONST_REF const_ref; // Constant value
('ob_inst', ctypes.c_void_p),# PVOID ob_inst; // There for compatibility, ptr should be used instead
('id', ctypes.c_ushort), # USHORT id; // Id value
('uint_val', ctypes.c_ushort),# USHORT uint_val; // Unsigned integer
('long_val', ctypes.c_long), # LONG long_val; // Long integer
('ulong_val', ctypes.c_ulong), # ULONG ulong_val; // Unsigned Long integer
('byte_val', ctypes.c_byte), # BYTE byte_val; // Byte value
]
class OB_DATA(ctypes.Structure):
_fields_ = [
('val' , OB_VALUE),
('info' , OB_INFO_FLAGS ),
('type' , OB_CLASS_ID),
]
POBDATA = ctypes.POINTER(OB_DATA)
函数调用代码
def rtRoutineSearch(inst, func_name:str, p_ob_data:POBDATA, args_len , function_or_event = 0)-> tuple :
rtCallInfo = RT_CALL_INFO()
rtCallInfo.enCallType = 2
if not inst:
och,_ = ob_global_reference("systemfunctions")
rtCallInfo.rtClassInfo.obClassHndl.class_id = och.class_id
rtCallInfo.rtClassInfo.obClassHndl.group_hndl = och.group_hndl
else:
rtCallInfo.rtClassInfo.obInst = inst
rtCallInfo.rtClassInfo.obClassHndl.class_id = ob_get_obinst_system_class(inst)
rtCallInfo.rtClassInfo.obClassHndl.group_hndl = ob_get_obinst_group_hndl(inst)
rtCallInfo.bDontTerminateRuntime = True
ovid=ctypes.pointer(ctypes.c_ushort())
pbvm.rtRoutineSearch.argtypes = (ctypes.c_void_p, RT_CALL_INFO,ctypes.c_char_p,ctypes.POINTER( OB_DATA ),
ctypes.c_uint,ctypes.c_int , ctypes.POINTER(ctypes.c_ushort))
p_func_name = ctypes.c_char_p(func_name.encode("GBK"))
#print("rtRoutineSearch的参数", p_ob_data)
find = pbvm.rtRoutineSearch(__obThis, rtCallInfo,
p_func_name, p_ob_data, args_len, function_or_event, ovid)
return find == 1, ovid.contents.value, rtCallInfo
def rtRoutineExec(rtCallInfo, pobdata:POBDATA, argslen,ovid,routtype=0)->tuple:
'''
调用pb函数,必须先调用rtRoutineSearch方法
'''
pbvm.rtRoutineExec.argtypes = (ctypes.c_void_p, RT_CALL_INFO,
ctypes.POINTER( OB_DATA ),ctypes.c_uint, ctypes.c_ushort,ctypes.c_int,ctypes.c_bool )
hrt = pbvm.rtRoutineExec(__obThis, rtCallInfo, pobdata, argslen, ovid, routtype, True)
if hrt != 0 : return False,None
pbvm.rtReturnValGet.restype = ctypes.POINTER( OB_DATA )
pob = pbvm.rtReturnValGet(__obThis)
return hrt==0, pob.contents
调用示例
from PyPB import RUN,messagebox,rtRoutineSearch,rtRoutineExec,OB_DATA,POBDATA,ob_set_data_string,INT_TYPE
import ctypes
def main():
#messagebox("提示","你好,PB!")
pobdata = ctypes.cast( (OB_DATA*2)(),POBDATA)
ob_set_data_string(pobdata[0],"提示")
ob_set_data_string(pobdata[1],"你好,PyPB")
ok,vid,rtCallInfo = rtRoutineSearch(None,"messagebox",pobdata,2)
if ok:
ok,rtObdata = rtRoutineExec(rtCallInfo,pobdata,2,vid)
print("数据类型",rtObdata.type==INT_TYPE)# 输出 数据类型 True
print("返回值",rtObdata.val.int_val)# 输出 返回值 1
RUN(__name__,__file__,main)
ff213141-26e2-4c64-9724-e841f33aa1b2