📄 extdllp.dpr
字号:
library extdll;
uses
SysUtils,
SyncObjs,
Dialogs,
Classes,
VComRes in 'VComRes.pas';
{
此DLL演示如何让VSPM具备自动轮询功能,并将轮询到的数据处理后,发给虚拟串口。
}
type
PDllData=^TDllData;
TDllData = array of Byte;
var
//COM口对应的资源
ComRes:TStringlist;
{$R *.res}
function GetComResByName(const VComName:string;var odata:TVComResClass):boolean;
var
AVComResClass:TVComResClass;
i1:Integer;
begin
//用串口名,获得对应的串口资源
Result:=false;
i1:=ComRes.IndexOf(VComName);
if i1<0 then exit;
AVComResClass:=TVComResClass(ComRes.Objects[i1]);
odata:=AVComResClass;
//释放资源
Result:=Assigned(AVComResClass);
end;
procedure InitExtDll(var act:integer);stdcall;
begin
//初始化扩展DLL资源
//VSPM在加载成功后调用此函数
ComRes:=TStringlist.Create;
act:=0;
end;
procedure FreeExtDll(var act:integer);stdcall;
begin
//释放扩展资源
//在DLL释放前,VSPM调用此函数
FreeAndNil(ComRes);
act:=0;
end;
procedure VComEvent(idata:Pointer;var act:integer);stdcall;
var
AVComResClass:TVComResClass;
SerialName:string;
i1:integer;
begin
//虚拟串口消息
//idata,虚拟串口号。
//act=0,虚拟串口打开消息
//act=1,虚拟串口关闭消息
//act=10,虚拟串口建立消息
//act=11,虚拟串口删除消息
SerialName:=PChar(idata);
case act of
0:begin
end;
1:begin
end;
10:begin
//建立虚拟串口,时初始化资源
//如果对应的串口资源已经建立,退出
if ComRes.IndexOf(SerialName)>=0 then exit;
//建立此串口资源
AVComResClass:=TVComResClass.Create(SerialName);
//添加资源到列表
ComRes.AddObject(SerialName,AVComResClass);
end;
11:begin
//删除虚拟串口
//如果没有对应的串口资源,退出
i1:=ComRes.IndexOf(SerialName);
if i1<0 then exit;
AVComResClass:=TVComResClass(ComRes.Objects[i1]);
//释放资源
if Assigned(AVComResClass) then FreeAndNil(AVComResClass);
end;
end;
act:=0;
//串口消息
end;
procedure VComQueryEvent(VComName:Pchar;
const odata:Pointer;var odatasize:Integer;
var act:integer);stdcall;export;
begin
//VComQueryEvent->虚拟串口,在串口对应的TCP/IP连接失效时,VSPM调用此函数
//此函数用于向应用程序发出串口数据报文。
//相当于应用程序从虚拟串口收到由TVComQueryEvetn产生的数据。
//参数:虚拟串口名称,输出数据,输出数据尺寸,
//act操作//(dll返回:act=0-发送数据)
//(dll返回:act=1-不发送数据,忽略此函数功能)
//!!VSPM Server模式下不调用此函数!!
//不需要此函数
act:=1;
end;
//NetworkQuery
procedure NetQueryEvent(VComName:Pchar;
const odata:Pointer;var odatasize:Integer;
var act:integer);stdcall;export;
begin
//不需要此函数
//NetQueryEvent->TCP/IP网络模拟发送函数,只有当网络连接正常时,
//并且虚拟串口关闭时才会调用此函数
//参数:虚拟串口名称,输出数据,输出数据尺寸,
//act操作 //(dll返回:act=0-发送数据)
//(dll返回:act=1-不发送数据,忽略此函数功能)
act:=1;
end;
//虚拟串口接收
procedure VComRecEvent(VComName:Pchar;idata:Pointer;idatasize:Integer;
const odata:Pointer;var odatasize:Integer;
var act:integer); stdcall;export;
var
s1:string;
lodata:PDllData;
begin
//对应的虚拟串口打开后,由VSPM线程一直调用此函数。
//因为由此DLL进行轮询,所以此函数忽略idata,
//模拟召唤报文
s1:='Polling:Need data';
lodata:=PDllData(odata);
//输出数据长度
odatasize:=Length(s1);
//复制数据到输出缓冲
Move(s1[1],lodata^,odatasize);
//发送到网络,
act:=0;
//500毫秒轮询一次
Sleep(500);
end;
procedure AfterVComRecEvent(VComName:Pchar;idata:Pointer;idatasize:Integer;
const odata:Pointer;var odatasize:Integer;
var act:integer); stdcall;export;
var
AWaitresult:TWaitResult;
AComResClass:TVComResClass;
begin
//发送数据到TCP/IP后执行此函数
act:=0;
odatasize:=idatasize;
//取得此串口对应的资源
if not GetComResByName(VComName,AComResClass) then exit;
//等待网络数据返回,如果1秒钟内远程没有返回数据,判定为轮询未响应。
AWaitresult:=AComResClass.GResponEvent.WaitFor(1000);
if (AWaitresult=wrSignaled) then
begin
//响应轮询
end else
begin
//在此处处理轮询未响应错误。
Beep;
exit;
end;
end;
procedure NetRecEvent(VComName:Pchar;idata:Pointer;idatasize:Integer;
const odata:Pointer;var odatasize:Integer;
var act:integer); stdcall;export;
var
s1:string;
lidata,lodata:PDllData;
AComResClass:TVComResClass;
begin
//当从网络接收到数据时,调用此函数
act:=1;
if (idatasize<=0) then exit;
lidata:=PDllData(idata);
lodata:=PDllData(odata);
SetLength(s1,idatasize);
//复制输入数据到本地缓冲
Move(lidata^,s1[1],idatasize);
if (s1='Polling:Data') then
begin
//取得此串口对应的资源
if not GetComResByName(VComName,AComResClass) then exit;
//如果收到的是数据报文,转换为显示报文
s1:=Format(#10#13'收到回应报文(%d):<%s>'#10#13,[AComResClass.FrameCount,s1]);
//输出数据长度
odatasize:=Length(s1);
//复制数据到输出缓冲
Move(s1[1],lodata^,odatasize);
//通知AfterVComRecEvent已经收到由设备返回来的数据
AComResClass.GResponEvent.SetEvent;
Inc(AComResClass.FrameCount);
end else
begin
//其他报文不处理
odatasize:=0;
act:=1;
end;
act:=0;
end;
procedure AfterNetRecEvent(VComName:Pchar;idata:Pointer;idatasize:Integer;
const odata:Pointer;var odatasize:Integer;
var act:integer); stdcall;export;
begin
//不处理此函数
odatasize:=idatasize;
act:=0;
end;
exports
InitExtDll,
FreeExtDll,
VComRecEvent,
AfterVComRecEvent,
VComQueryEvent,
NetRecEvent,
AfterNetRecEvent,
NetQueryEvent,
VComEvent;
begin
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -