dll二次开发:下载消费机的消费记录失败!

YUAN168 2014-10-20 11:29:52
1.设置端口信息
SetConnectInfo(IConnectType:Integer;InPort:Integer;ITcpAddress:string;InBaud:Word):Boolean; stdcall;far external 'ICXF.DLL' name '_SetConnectInfo@16';
功能:用于设置机器的通讯方式(串口还是tcp/ip通讯),只要是两种方式都可以通讯的涵数调用之前,都必须先调用此涵数来区分通讯方式
返回值:布尔型,调用成功返回真(TRUE),否则返回假(FALSE)
参数:
IConnectType:机器通方式,数据类型:整数型,取值0或1(0为串口通讯,1为tcp/ip通讯)
InPort:串口号,数据类型:整数型,取值从1开始,IConnectType为1即通讯方式是TCP/IP时,该参数不起作用,带入0就可以了
ITcpAddress: IP地址(例如192.168.001.005,注意:不能简化写成:192.168.1.5),数据类型:字符串;
InBaud:串口通讯时为机器通讯的波特率,波特率为9600,TCP/IP通讯时为端口号,端口号为9760+机器号
例如机号为1时,端口号是9761,机号为2时,端口号是9762,以此类推
调用实例:
232/485通讯,串口号为1,机号为1 SetConnectInfo(0,1,'',9600)
TCP/IP通讯,IP为192.168.001.022,机号为1, SetConnectInfo(1,0,'192.168.001,022',9760+1)
9.手动下载流水
function ReadLSList(MacNO: Byte; Flag:Char ;var listcount:Integer; ls: PChar): integer; stdcall; far; external MDllName Name '_ReadLSList@16';
返回值:整数型,1代表调用成功,否则代表调用失败
//打开端口
function OpenCOMM():Boolean; stdcall;far external MDllName name '_OpenCOMM@0';
//关闭端口
function CloseCOMM():Boolean; stdcall;far external MDllName name '_CloseCOMM@0';
===========================以上是帮助的dll================
SetConnectInfo(1,0,'200.200.200.240',9762);
RTurn:=ReadAllTotalCountAndMoney(002,ConsumeCount,ConsumeMoney);
GetMem(RecodeBuf,1300);
OpenCOMM();
ReadLSList(2,'F',listcount,RecodeBuf);
------------以上是delphi----执行,没有问题

DECLARE INTEGER _SetConnectInfo@16 IN "ICXF.DLL" AS SetConnectInfo Integer ,Integer ,String ,INTEGER
IF SetConnectInfo(1,0,"200.200.200.240",9760+2)<>1
MESSAGEBOX("连接消费机失败!",0+64,"系统提示")
RETURN
ENDIF


DECLARE INTEGER _OpenCOMM@0 IN "ICXF.DLL" AS OpenCOMM
DECLARE INTEGER _CloseCOMM@0 IN "ICXF.DLL" AS CloseCOMM

DECLARE INTEGER _ReadLSList@16 IN "ICXF.DLL" AS ReadLSList INTEGER MacNO,STRING cflag,INTEGER @ nCount ,STRING @ RecodeBuf
lstatus=OpenCOMM()
IF lstatus<>1
MESSAGEBOX("打开串口失败!",0+64,"系统提示")
CloseCOMM()
RETURN
ENDIF
cflag="F"
RecodeBuf=REPLICATE(CHR(0),1300)
nCount=0
nReturn=ReadLSList(002,cflag,@ nCount,@ RecodeBuf)

MESSAGEBOX(RecodeBuf)
IF nReturn<>1
MESSAGEBOX("读取消费记录失败!",0+64,"系统提示")
CloseCOMM()
CLEAR DLLS
ELSE
CloseCOMM()
CLEAR DLLS
RETURN
ENDIF
===============以上是vfp代码=========
RecodeBuf 这个就是取不到值,都是空的

RecodeBuf=strconv(REPLICATE(CHR(0),1300),15) &&转换也是取不到
...全文
415 18 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
都市夜猫 2014-10-21
  • 打赏
  • 举报
回复
1300 是怎样得出的不得而知,36 条消费记录需要多大的内存块来回填数据?1300 是否足够?从你给出的 Deliph 示例代码来看,只是用 GetMem 分配了一块长度为 1300 的未初始化内存,然后传递给 ReadLSList 函数来回填数据,不知道这个 dll 是否把 RecordBuf 作为 C 字符数组指针来判断字符串的长度?既然调用没有出错,只是没有数据,不妨试试不对分配的内存进行初始化,或者将分配的尺寸增大一些试试。

试验1 - 加大分配的内存:
nSize = 8000
RecodeBuf = GlobalAlloc(64, nSize)

试验2 - 分配的内存不填 0:
nSize = 5000
RecodeBuf = GlobalAlloc(64, nSize+1)
Sys(2600, RecodeBuf, nSize, Replicate('x', nSize))
YUAN168 2014-10-21
  • 打赏
  • 举报
回复
DECLARE INTEGER _SetConnectInfo@16 IN "ICXF.DLL" AS SetConnectInfo Integer ,Integer ,String ,INTEGER IF SetConnectInfo(1,0,"200.200.200.240",9760+2)<>1 MESSAGEBOX("连接消费机失败!",0+64,"系统提示") RETURN ENDIF DECLARE INTEGER _OpenCOMM@0 IN "ICXF.DLL" AS OpenCOMM DECLARE INTEGER _CloseCOMM@0 IN "ICXF.DLL" AS CloseCOMM Declare Long GlobalAlloc in win32api Long uFlags, Long dwBytes DECLARE LONG GlobalFree IN WIN32API LONG hMem DECLARE INTEGER _ReadLSList@16 IN "ICXF.DLL" AS ReadLSList INTEGER MacNO,STRING cflag,INTEGER @nCount ,Long RecodeBuf lstatus=OpenCOMM() IF lstatus<>1 MESSAGEBOX("打开串口失败!",0+64,"系统提示") CloseCOMM() RETURN ENDIF cflag="F" RecodeBuf=GlobalAlloc(0x0040,1300) nCount=0 nReturn=ReadLSList(002,cflag,@ nCount,RecodeBuf) MESSAGEBOX(nReturn) IF nReturn<>1 MESSAGEBOX("读取消费记录失败!",0+64,"系统提示") CloseCOMM() GlobalFree(RecodeBuf) CLEAR DLLS ELSE cRecords = Sys(2600,RecodeBuf, 1300) MESSAGEBOX(STRCONV(cRecords ,15)) CloseCOMM() GlobalFree(RecodeBuf) CLEAR DLLS ENDIF
oldbbb 2014-10-21
  • 打赏
  • 举报
回复
Delphi的PChar类型,是一个32位指针,PChar作为字符串使用要自己分配和释放内存,以#0作为字符串结束符。
都市夜猫 2014-10-21
  • 打赏
  • 举报
回复
第二个试验错了


文档中有没有 RecodeBuf 大小的计算方法?
YUAN168 2014-10-21
  • 打赏
  • 举报
回复
DECLARE INTEGER _SetConnectInfo@16 IN "ICXF.DLL" AS SetConnectInfo Integer ,Integer ,String ,INTEGER IF SetConnectInfo(1,0,"200.200.200.240",9760+2)<>1 MESSAGEBOX("连接消费机失败!",0+64,"系统提示") RETURN ENDIF DECLARE INTEGER _OpenCOMM@0 IN "ICXF.DLL" AS OpenCOMM DECLARE INTEGER _CloseCOMM@0 IN "ICXF.DLL" AS CloseCOMM Declare Long GlobalAlloc in win32api Long uFlags, Long dwBytes DECLARE LONG GlobalFree IN WIN32API LONG hMem DECLARE INTEGER _ReadLSList@16 IN "ICXF.DLL" AS ReadLSList INTEGER MacNO,STRING cflag,INTEGER @nCount ,Long RecodeBuf lstatus=OpenCOMM() IF lstatus<>1 MESSAGEBOX("打开串口失败!",0+64,"系统提示") CloseCOMM() RETURN ENDIF cflag="F" nSize = 8000 RecodeBuf = GlobalAlloc(64, nSize) nCount=0 nReturn=ReadLSList(002,cflag,@ nCount,RecodeBuf) MESSAGEBOX(nReturn) IF nReturn<>1 MESSAGEBOX("读取消费记录失败!",0+64,"系统提示") CloseCOMM() GlobalFree(RecodeBuf) CLEAR DLLS ELSE cRecords = Sys(2600,RecodeBuf, 1300) MESSAGEBOX(STRCONV(cRecords ,15)) CloseCOMM() GlobalFree(RecodeBuf) CLEAR DLLS ENDIF =============试验1,失败了,跟原来一样============= DECLARE INTEGER _SetConnectInfo@16 IN "ICXF.DLL" AS SetConnectInfo Integer ,Integer ,String ,INTEGER IF SetConnectInfo(1,0,"200.200.200.240",9760+2)<>1 MESSAGEBOX("连接消费机失败!",0+64,"系统提示") RETURN ENDIF DECLARE INTEGER _OpenCOMM@0 IN "ICXF.DLL" AS OpenCOMM DECLARE INTEGER _CloseCOMM@0 IN "ICXF.DLL" AS CloseCOMM Declare Long GlobalAlloc in win32api Long uFlags, Long dwBytes DECLARE LONG GlobalFree IN WIN32API LONG hMem DECLARE INTEGER _ReadLSList@16 IN "ICXF.DLL" AS ReadLSList INTEGER MacNO,STRING cflag,INTEGER @nCount ,Long RecodeBuf lstatus=OpenCOMM() IF lstatus<>1 MESSAGEBOX("打开串口失败!",0+64,"系统提示") CloseCOMM() RETURN ENDIF cflag="F" nSize = 5000 RecodeBuf = GlobalAlloc(64, nSize+1) nCount=0 nReturn=ReadLSList(002,cflag,@ nCount,RecodeBuf) MESSAGEBOX(nReturn) IF nReturn<>1 MESSAGEBOX("读取消费记录失败!",0+64,"系统提示") CloseCOMM() GlobalFree(RecodeBuf) CLEAR DLLS ELSE cRecords =Sys(2600, RecodeBuf, nSize, Replicate('x', nSize)) MESSAGEBOX(STRCONV(cRecords ,15)) &&这里出来的是 78787878之类的,一模一样,应当也是失败了 CloseCOMM() GlobalFree(RecodeBuf) CLEAR DLLS ENDIF
YUAN168 2014-10-20
  • 打赏
  • 举报
回复
nCount =36,也就是说一次性取的是36条消费记录,这个值可以取到 nReturn 返回的是 1 就是 RecodeBuf 这个取不到值
都市夜猫 2014-10-20
  • 打赏
  • 举报
回复
1. nReturn 返回值是多少? 2. nCount 返回值是多少?
都市夜猫 2014-10-20
  • 打赏
  • 举报
回复
把你最后的代码贴出来
YUAN168 2014-10-20
  • 打赏
  • 举报
回复
两种 方式我都试过了,都是空的啊,出来都是 0000000
都市夜猫 2014-10-20
  • 打赏
  • 举报
回复
见9楼,晕死,代码都抄错,不要那个 @ 这个要传值,不能传引用
YUAN168 2014-10-20
  • 打赏
  • 举报
回复
Declare Long GlobalAlloc in win32api Long uFlags, Long dwBytes DECLARE LONG GlobalFree IN WIN32API LONG hMem DECLARE INTEGER _ReadLSList@16 IN "ICXF.DLL" AS ReadLSList INTEGER MacNO,STRING cflag,INTEGER @nCount ,Long RecodeBuf lstatus=OpenCOMM() IF lstatus<>1 MESSAGEBOX("打开串口失败!",0+64,"系统提示") CloseCOMM() RETURN ENDIF cflag="F" RecodeBuf=GlobalAlloc(0x0040,1300) nCount=0 nReturn=ReadLSList(002,cflag,@ nCount,@ RecodeBuf) MESSAGEBOX(nReturn) IF nReturn<>1 MESSAGEBOX("读取消费记录失败!",0+64,"系统提示") CloseCOMM() GlobalFree(RecodeBuf) CLEAR DLLS ELSE cRecords = Sys(2600, RecodeBuf, 1300) &&可以执行到这,RecodeBuf 是一个大数据 如17785678,不过 cRecords 全是 0000000,没有数据的 MESSAGEBOX(STRCONV(cRecords ,15)) CloseCOMM() GlobalFree(RecodeBuf) CLEAR DLLS ENDIF
都市夜猫 2014-10-20
  • 打赏
  • 举报
回复
直接复制代码吧,这里不对 nReturn=ReadLSList(002,cflag,@ nCount,@ RecodeBuf)
都市夜猫 2014-10-20
  • 打赏
  • 举报
回复
你的 0x0040 是不是输入了字母 O ? 16 进制的 0x0040 改成 10 进制的 64 RecodeBuf=GlobalAlloc(64,1300)
YUAN168 2014-10-20
  • 打赏
  • 举报
回复
不好意思,上面的错误 是我自已造 成的 Declare Long GlobalAlloc in win32api Long uFlags, Long dwBytes DECLARE LONG GlobalFree IN WIN32API LONG hMem DECLARE INTEGER _ReadLSList@16 IN "ICXF.DLL" AS ReadLSList INTEGER MacNO,STRING cflag,INTEGER @nCount ,Long @RecodeBuf lstatus=OpenCOMM() IF lstatus<>1 MESSAGEBOX("打开串口失败!",0+64,"系统提示") CloseCOMM() RETURN ENDIF cflag="F" RecodeBuf=GlobalAlloc(0x0040,1300) nCount=0 nReturn=ReadLSList(002,cflag,@ nCount,@ RecodeBuf) &&这里直接就退出去了 MESSAGEBOX(nReturn)
YUAN168 2014-10-20
  • 打赏
  • 举报
回复
DECLARE INTEGER _ReadLSList@16 IN "ICXF.DLL" AS ReadLSList INTEGER MacNO,STRING cflag,INTEGER @nCount ,Long RecodeBuf lstatus=OpenCOMM() IF lstatus<>1 MESSAGEBOX("打开串口失败!",0+64,"系统提示") CloseCOMM() RETURN ENDIF cflag="F" RecodeBuf=GlobalAlloc(0x0040,1300) && 这里就报错了: data type mismatch nCount=0 nReturn=ReadLSList(002,cflag,@ nCount,@ RecodeBuf)
都市夜猫 2014-10-20
  • 打赏
  • 举报
回复
*-- 注意最后一个参数的声明有改变
DECLARE INTEGER _ReadLSList@16 IN "ICXF.DLL" AS ReadLSList ;
INTEGER MacNO,STRING cflag,INTEGER @ nCount, Long RecodeBuf

这里有没有改?
YUAN168 2014-10-20
  • 打赏
  • 举报
回复
nReturn=ReadLSList(002,cflag,@ nCount, RecodeBuf) &&执行到这里出现 data type mismatch MESSAGEBOX(VARTYPE(RecodeBuf)) && 这里的类型是 N 定义时给的是 Long dwBytes
都市夜猫 2014-10-20
  • 打赏
  • 举报
回复
直接传 vfp 的字符串给外部函数是有风险的,特别是比较大的字符串时。原因是 vfp 的垃圾收集器会随时整理内存,由此可能导致原来分配的字符串被移动。如果读过 vfp 帮助中 LCK 部分,会看到用 C 编写 FLL 时,分配的内存块传给内部或外部函数时,需要先调用 _HLock 函数锁住。由于在 vfp 代码中无法直接调用 LCK 的 API 函数 _HLock,所以采用直接调用 Windows API 提供的内存分配函数来替代,也就是调用 ReadLSList 前,先手工分配一块固定内存作为存储读取数据的缓存。
暂且假定是这个原因吧,对不对要看试验结果才能断定,做如下修改试试:
...
IF lstatus<>1
MESSAGEBOX("打开串口失败!",0+64,"系统提示")
CloseCOMM()
RETURN
ENDIF

Declare Long GlobalAlloc in win32api Long uFlags, Long dwBytes
Declare Long GlobalFree in win32api Long hMem
*-- 注意最后一个参数的声明有改变
DECLARE INTEGER _ReadLSList@16 IN "ICXF.DLL" AS ReadLSList ;
INTEGER MacNO,STRING cflag,INTEGER @ nCount, Long RecodeBuf

cflag="F"
nCount=0
RecodeBuf = GlobalAlloc(0x0040, 1300)
nReturn=ReadLSList(002,cflag,@ nCount, RecodeBuf)

IF nReturn<>1
MESSAGEBOX("读取消费记录失败!",0+64,"系统提示")
Else
cRecords = Sys(2600, RecodeBuf, 1300)
MessageBox(Strconv(cRecords, 15))
EndIf
CloseCOMM()
GlobalFree(RecodeBuf)

CLEAR DLLS
...

2,748

社区成员

发帖
与我相关
我的任务
社区描述
VFP,是Microsoft公司推出的数据库开发软件,用它来开发数据库,既简单又方便。
社区管理员
  • VFP社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧