200分倾家荡产求解!!程序提示“非法操作”,又是DLL问题,同时也是串行口通讯问题。(200分)

  • 主题发起人 主题发起人 cym_cym
  • 开始时间 开始时间
C

cym_cym

Unregistered / Unconfirmed
GUEST, unregistred user!
各位大侠,快帮帮我吧,快一周了.......真惨啊!
闲话少说,书归正转!

背景:本人要编一个采集程序,已经有一个DLL提供给我,是c编译的(有c++及vb的demo,都是
好使的),用来完成底层数据采集。我要用Delphi完成她,我把它放在一个定时器事件中,
当事件结束,系统提示“非法操作”,当我把这句注释掉后,一切正常,看样子就是调用
DLL惹的祸,咳! :((
相关内容:
这本来是一个串行口通讯的问题,但产品提供商给了我个DLL。原来我用串行口通讯控件
CommPort 2.61也能采集到数据,但几个小时后就没有数据返回了(有时是几分钟......
:(( ),马上关闭程序,立即重新运行,数据又出来了,气死我了。基本排除下位机故
障可能,问题出在程序中。于是换用厂商给的DLL,就出现上述问题了。我估计可能是使
用了开放式数组作为参数所致,因为DLL调用好像有这方面的说明,即不能用不定长度的
参数,如String类型,否则轻的是内存错误,严重的就是俺这样的问题。但我看数组好像
都是开放式的,如何解决呢?
目的:解决问题啊!!最好两个方案都解决!!(嘿嘿,胃口大点...... p)
手段:还是靠大家帮忙啊!!提出有益建议方法的,统统有分(反正分也多)最好是有实例的。
其他:我还想要一个内存调试的工具,如BoundsChecker,我有一个6.01版本的,最新是6.5版本的,
支持Delphi5和c++Builder5, 谁有?或请告诉我下载地点(他的老窝就免了,我去过了,
填了一大堆表格,还不知道能不能给你一个14天的预览版),一定要有序列号(不然怎么
用?)。要是有其他优秀的类似工具,满足Delphi5和c++Builder5能用也可以。
附录:
这里就是程序部分,第一部分是用DLL的程序,第二部分是用CommPort2.61的程序,第三部分
是在VB6.0中使用DLL的说明部分(请高手帮忙看看我改的在Delphi中的定义声明对不对)。
第一部分:
定时器调用部分
procedure TForm1.Timer2Timer(Sender: TObject);
begin
.
.
.
label2.Caption := ModelName[currentmodel];
label4.Caption :='2';
//ModelName[currentmodel]是采集模块地址,字符型
ModelInData := strtoint(ModelName[currentmodel]);
portreturn:=0;
portreturn:=ltm_read_id(CommPort,ModelInData,8,idbuf);
Timer2.Interval := 0
end;

DLL声明定义部分:我把它做成了一个单元,这样容易移植到其他程序中
unit ImportUnit;

interface
Const ERR_OK : Longint = -1;
Const ERR_MEMORY : Longint = -2;
Const ERR_COF : Longint = -3;
Const ERR_PORT : Longint = -4
Const ERR_INIT : Longint = -5;
Const ERR_SETUP : Longint = -6;
Const ERR_PORT_NUM : Longint = -7;
Const ERR_NORESPONSE : Longint = -8
Const ERR_RECEIVELESS : Longint = -9;
Const ERR_INVALIDDATA : Longint = -10
Type Cfg=Record
oldaddr : Byte
newaddr : Byte
mytype : Byte
baud : Byte
setbaud : Byte
dataform : Byte
total_num : Longint
ch_status : Byte
ch_num : array[0..7] of Byte
mname : pchar //这两个原来用String就不行
version : pchar
end;
Var
mcfg : Cfg
databuf : array[0..2100] of Byte
idbuf : array[0..4200] of Byte
port : Longint;
baud : Longint;
channo : Longint;
senNo : Integer
freshtime : Longint;
maddress : Longint;
errcode : Longint;
startid : Byte
stopid : Byte
Function ltm_com_open(port : longint baudd : longint rtsdtr : longint) : integer
Stdcall External'ltm8000d.dll'
Function ltm_com_close(port : Longint) : Longint;
Stdcall; External 'ltm8000d.dll'
Function ltm_read_config(port : Longint;addr : Byte;Var mcfg : Cfg) : Longint;
Stdcall External'ltm8000d.dll'
Function ltm_read_id(port : Longint;addr : Byte;channel : Longint;
Var idbuf :array of byte) : Longint Stdcall; External'ltm8000d.dll'
Function ltm_read_temp(port : Longint;addr : Byte;channel : Longint;
Var databuf :array of byte) : Longint Stdcall; External'ltm8000d.dll'
Function ltm_soft_reset(port : Longint;addr : Byte) : Longint
Stdcall; External 'ltm8000d.dll'
Function ltm_set_config(port : Longint Var mcfg : cfg) : Longint;
Stdcall; External 'ltm8000d.dll'

implementation

end.

第二部分:
procedure TForm1.Timer2Timer(Sender: TObject);
var
ss : string ;
begin
.
.
.
ComPort1.ClearBuffer(true,true)
label14.Caption :='1';
label15.Caption := ModelName[currentmodel];
ss := '$'+ ModelName[currentmodel] +'6' + Chr(13)
ComPort1.WriteStr(ss)
Timer2.Interval := 0
Timer4.Interval := 1000
end;
procedure TForm1.Timer4Timer(Sender: TObject);
label12.Caption := timetostr(time);
ComPort1.ReadStr(Str1, Comport1.InputCount );
str:=Copy(str1,2, Length(Str1)-2);
edit1.text := ''
edit2.text := ''
stringgrid1.Rows[1].Clear
stringgrid1.Rows[2].Clear
stringgrid1.Rows[3].Clear
stringgrid1.Rows[4].Clear
stringgrid1.Rows[5].Clear
edit1.text := strtemp
edit2.text := inttostr(datanum)
Timer2.Interval := 10
end;
第三部分:
在VB6.0中使用DLL的说明:
Rem 变量声明

Public Type Cfg
oldaddr As Byte
newaddr As Byte
type As Byte
baud As Byte
setbaud As Byte
dataform As Byte
total_num As Long
ch_status As Byte
ch_num(7) As Byte
mname As String * 8
version As String * 8
End Type --------配置结构定义

Public mcfg As Cfg
Public databuf(2100) As Byte
Public idbuf(4200) As Byte
Public port As Long
Public baud As Long
Public channo As Long
Public senNo As Integer
Public freshtime As Long
Public maddress As Long
Public errcode As Long

Rem 动态连接库函数声明
Rem Public Declare Function ltm_com_close Lib "d:/ltm8001/dll/ltm8000d.dll"
(ByVal port As Long) As Long
Public Declare Function ltm_com_open Lib "ltm8000d.dll" (ByVal port As Long,
ByVal baud As Long, ByVal rtsdtr As Long) As Long
Public Declare Function ltm_com_close Lib "ltm8000d.dll" (ByVal port As Long) As Long
Public Declare Function ltm_read_config Lib "ltm8000d.dll" (ByVal port As Long,
ByVal addr As Byte, mcfg As Cfg) As Long
Public Declare Function ltm_read_temp Lib "ltm8000d.dll" (ByVal port As Long,
ByVal addr As Byte, ByVal channel As Long, databuf As Any) As Long
Public Declare Function ltm_read_id Lib "ltm8000d.dll" (ByVal port As Long,
ByVal addr As Byte, ByVal channel As Long, idbuf As Any) As Long
Public Declare Function ltm_soft_reset Lib "ltm8000d.dll" (ByVal port As Long,
ByVal addr As Byte) As Long
Public Declare Function ltm_set_config Lib "ltm8000d.dll" (ByVal port As Long,
ByRef mcfg As Cfg) As Long
Public Const ERR_OK As Long = -1, ERR_MEMORY As Long = -2, ERR_COF As Long = -3,
ERR_PORT As Long = -4
Public Const ERR_INIT As Long = -5, ERR_SETUP As Long = -6,
ERR_PORT_NUM As Long = -7, ERR_NORESPONSE As Long = -8
Public Const ERR_RECEIVELESS As Long = -9, ERR_INVALIDDATA As Long = -10
Public startid As Byte
Public stopid As Byte
结束****************
 
定义改成:
Function ltm_read_id(port : Longint;addr : Byte;channel : Longint;
idbuf :Pointer) : Longint Stdcall; External'ltm8000d.dll'
试试.
调用改成
portreturn:=ltm_read_id(CommPort,ModelInData,8,@(idbuf[0]));
 
看情况是你声明DLL不对了,这样改:
先加两个新类型,是固定数组的
Type Tidbuf = array[0..4200] of Byte;
Type Tdatabuf = array[0..1600] of Byte

然后在如下声明变量
Var
.
.
databuf : Tdatabuf;
idbuf : Tidbuf
.
声明函数时,把相应变量类型改为对应的就行了。
 
to Another_eYes
你的我没太看明白(真苯 ^o^),是定义一个指针吗?那么能传送指针到DLL中去?
它可要传送一个数组啊!然后回传数据。
to zh_hero
谢谢你,你的方法好极了,一试就通了。不过你打错数字了,嘻嘻嘻嘻

to all
其他问题有人解吗?快点呀,急!
 
接受答案了.
 
后退
顶部