Linux下Python调用SAP NW RFC出现LP_RFC_CONNECTION_PARAMETER类型不匹配错误
问题:Python调用SAP NetWeaver RFC库从Windows迁移到Linux后参数类型错误
从SAP官方博客获取的Python调用SAP NetWeaver RFC库的代码在Windows上运行正常,迁移到Linux环境时仅将windll.LoadLibrary(SAPNWRFC)替换为cdll.LoadLibrary(SAPNWRFC),却出现如下错误:
Traceback (most recent call last): File "test.py", line 3, in <module> data = dataProcessing("USR01") File "src/utils.py", line 4, in dataProcessing queryData = query(table) File "src/readTable.py", line 9, in query hRFC = SAP.RfcOpenConnection(connection(), 5, RfcErrInf) ctypes.ArgumentError: argument 1: <type 'exceptions.TypeError'>: expected LP_RFC_CONNECTION_PARAMETER_Array_5 instance instead of RFC_CONNECTION_PARAMETER_Array_5
相关代码
sapnwrfc.py 核心代码
from ctypes import * import platform, os #-Structures------------------------------------------------------------ class RFC_ERROR_INFO(Structure): _fields_ = [("code", c_long), ("group", c_long), ("key", c_wchar * 128), ("message", c_wchar * 512), ("abapMsgClass", c_wchar * 21), ("abapMsgType", c_wchar * 2), ("abapMsgNumber", c_wchar * 4), ("abapMsgV1", c_wchar * 51), ("abapMsgV2", c_wchar * 51), ("abapMsgV3", c_wchar * 51), ("abapMsgV4", c_wchar * 51)] class RFC_CONNECTION_PARAMETER(Structure): _fields_ = [("name", c_wchar_p), ("value", c_wchar_p)] #-Constants(省略部分常量定义)------------------------------------------------------------- #-Variables------------------------------------------------------------- ErrInf = RFC_ERROR_INFO; RfcErrInf = ErrInf() ConnParams = RFC_CONNECTION_PARAMETER * 5; RfcConnParams = ConnParams() SConParams = RFC_CONNECTION_PARAMETER * 3; RfcSConParams = SConParams() #-Library--------------------------------------------------------------- if str(platform.architecture()[0]) == "32bit": os.environ['PATH'] += ";/home/marilan/Nunes/Klyra/nwrfcsdk/lib" SAPNWRFC = "/home/marilan/nwrfcsdk/lib/libsapnwrfc.so" elif str(platform.architecture()[0]) == "64bit": os.environ['PATH'] += ";/home/marilan/Nunes/Klyra/nwrfcsdk/lib" SAPNWRFC = "/home/marilan/nwrfcsdk/lib/libsapnwrfc.so" SAP = cdll.LoadLibrary(SAPNWRFC) #-Prototypes------------------------------------------------------------ # 省略其他函数原型定义 SAP.RfcOpenConnection.argtypes = [POINTER(ConnParams), c_ulong, POINTER(ErrInf)] SAP.RfcOpenConnection.restype = c_void_p
connection() 函数代码
from sapnwrfc import * def connection(): FileName = "sapnwrfc.py" exec(compile(open(FileName).read(), FileName, "exec")) #-Connection parameters------------------------------------------------- RfcConnParams[0].name = "ASHOST"; RfcConnParams[0].value = "I put my credentials here" RfcConnParams[1].name = "SYSNR" ; RfcConnParams[1].value = "I put my credentials here" RfcConnParams[2].name = "CLIENT"; RfcConnParams[2].value = "I put my credentials here" RfcConnParams[3].name = "USER" ; RfcConnParams[3].value = "I put my credentials here" RfcConnParams[4].name = "PASSWD"; RfcConnParams[4].value = "I put my credentials here" return RfcConnParams
解决方案
错误核心是Windows和Linux下ctypes处理数组指针的逻辑差异:Windows的windll会自动将数组转为指针传递,但Linux的cdll需要显式传递指针。需做以下修改:
1. 修正RfcOpenConnection的参数类型定义
将原代码中:
SAP.RfcOpenConnection.argtypes = [POINTER(ConnParams), c_ulong, POINTER(ErrInf)]
修改为:
SAP.RfcOpenConnection.argtypes = [POINTER(RFC_CONNECTION_PARAMETER), c_ulong, POINTER(RFC_ERROR_INFO)]
直接指定数组元素的指针类型,而非数组的指针类型。
2. 调用时显式传递指针
将调用代码:
hRFC = SAP.RfcOpenConnection(connection(), 5, RfcErrInf)
修改为:
params = connection() hRFC = SAP.RfcOpenConnection(byref(params), 5, byref(RfcErrInf))
使用byref()函数显式获取数组和错误信息结构体的指针。
3. 移除connection()函数中的冗余代码
删除connection()里重复加载模块的exec语句,直接使用导入的变量:
from sapnwrfc import RfcConnParams def connection(): #-Connection parameters------------------------------------------------- RfcConnParams[0].name = "ASHOST"; RfcConnParams[0].value = "你的ASHOST地址" RfcConnParams[1].name = "SYSNR" ; RfcConnParams[1].value = "你的系统编号" RfcConnParams[2].name = "CLIENT"; RfcConnParams[2].value = "你的客户端编号" RfcConnParams[3].name = "USER" ; RfcConnParams[3].value = "你的用户名" RfcConnParams[4].name = "PASSWD"; RfcConnParams[4].value = "你的密码" return RfcConnParams
内容的提问来源于stack exchange,提问作者Nathan Nunes
相关产品推荐
相关产品推荐

