编程通常所说的血型是指,调用DLL接口,是不是指调用interface

exe程序模块调用dll模块接口返回对象的问题!
[问题点数:40分,结帖人suxinpingtao51]
exe程序模块调用dll模块接口返回对象的问题!
[问题点数:40分,结帖人suxinpingtao51]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
匿名用户不能发表回复!|
每天回帖即可获得10分可用分!小技巧:
你还可以输入10000个字符
(Ctrl+Enter)
请遵守CSDN,不得违反国家法律法规。
转载文章请注明出自“CSDN(www.csdn.net)”。如是商业用途请联系原作者。查看:1203|回复:3
助理工程师
楼主在一家医院上班,医院的HIS(医院信息系统)由第三方制作,有些功能不能达到医院要求,请制作公司改动一是慢,二是要MONEY,SO,楼主动起了自己增加功能的脑筋,我以前学的软件专业,但主攻网络,编程方面基本自学。
我们医院与市医保对接使用东软公司开发的接口,东软提供了一个DLL(动态链接库)文件一份公开的接口调用文档。
多年前,还在上学的时候用过VB,这次依然选择了vb.net(2008版)作为开发工具。
遇到的第一个问题是如何在程序里调用DLL(汗,确实没用过),寻访度娘(“VB调用DLL”),找到了调用DLL方法如下:复制内容到剪贴板代码:&DllImport(&SiInterface.dll&, EntryPoint:=&INIT&)& Public Shared Function INIT(ByVal OutputInfo As String) As Integer
End Function
&DllImport(&SiInterface.dll&, EntryPoint:=&BUSINESS_HANDLE&)& Public Shared Function BUSINESS_HANDLE(ByVal inputData As String, &Out()& ByVal outputData As StringBuilder) As Integer
End Function东软提供的DLL名为SiInterface.dll,里面有两个可调用的接入点,一个是INIT(用于接口初始化,测试网络连通性),一个是BUSINESS_HANDLE(用于处理和查询业务数据)。
首先需要初始化接口,我选择在加载窗体的时候初始化。复制内容到剪贴板代码:
result = DLLImports.INIT(inputdata)如果调用成功返回0。
一开始调试,一直调用不成功,提示“未找到配置文件”,多番查询,结果DLL还需要一个同名的ini文件(文档里面根本未提到,操蛋),我直接在HIS商软件目录里找了一个(因为接口是规范统一的,所以可以直接用)。
注意把DLL和INI放在程序的同目录就行。
初始化成功后,就可以调用BUSINESS_HANDLE了。复制内容到剪贴板代码:
result = DLLImports.BUSINESS_HANDLE(inputdata, l_outputdata)调用成功结果同样返回0。
这样就基本完成了一次接口的调用,当然离功能成型还差很远,不过自己感觉很棒,加深了对医保的理解,同时也能够给单位做些事情。
(38.59 KB)
本帖最后由 windbadboy 于
22:22 编辑
自学+研究精神可嘉
你这是内蒙的吧,我就是干这的
助理工程师
引用:原帖由 zh 于
20:16 发表
你这是内蒙的吧,我就是干这的 重庆的,用的东软接口。
你是程序工程师?Delphi使用模块化开发,可以采用DLL或者BPL,两者的区别是BPL只能被同版本的Delphi使用,DLL可以被不同版本和不同开发工具的开发的软件调用。因此我们的软件大多使用Delphi作为界面以及部分DLL模块的开发工具。DLL模块之间通过接口方式调用。&1.对象创建采用工厂模式,每个DLL负责某个对象或若干个对象的创建及释放,例如:DLL工程为http客户端(prjHttp.DLL)模块,通过DLL导出的GetHttpClientFactory获取http客户端工厂接口,通过接口创建Http客户端和释放Http客户端,工程包括3个文件:工程文件,实现单元,接口单元。调用此DLL的程序仅需要包含接口单元。&DLL工程文件1 library prjH2 3 uses
System.SysUtils,
System.Classes,
utHTTPClient in 'utHTTPClient.pas';4 5 {$R *.res}6 7 exports
GetHttpClientF 9 end.utHttpClient示例unit utHttpCinterfaceuses utBaseObject, utHttpInterface, Classes, SysUtype
THTTPClientConnection = class(TIntObject, IHTTPClientConnection)
function Connect: B
function Info: IHTTPClientConnectionI
function TcpConnection: ITcpC
function DataConnection: IC
function Param:IHttpClientConnectionP
constructor C
destructor D override;
THttpClientConnectionFactory = class(TIntObject, IHttpClientConnectionFactory)
FObjectPool: THTTPClientConnectionP
constructor C
destructor D override;
procedure CreateHttpClient(out Conn: IHTTPClientConnection);
procedure DestroyHttpClient(var aClient);
end;function GetHttpClientFactory: IHttpClientConnectionFimplementation............var
HttpClients: THttpClientConnectionFfunction GetHttpClientFactory: IHttpClientConnectionFbegin
if not Assigned(HttpClients) then
HttpClients := THttpClientConnectionFactory.C
:= HttpCend;initializationfinalization
if Assigned(HttpClients) then FreeAndNil(HttpClients);end.&utHttpInterface接口文件示例unit utHttpIinterfaceuses utBaseIconst
IID_IHTTPClientConnectionInfo
= '{24C3D6BF-EC3D-4783-AD98-A5C6E4F24F19}';
IID_IHTTPClientConnectionParam
= '{0FA49A71-48BF-40CD-9D77-63B233C4F717}';
IID_IHTTPClientConnection
= '{78C39E26-A690--C}';
IID_IHTTPClientConnectionEvent
= '{2FB0AC19--B105-EBC}';
IID_IHttpClientConnectionFactory
= '{429C5C2B-C1E3--E3B943619EFD}';
GUID_IHTTPClientConnectionInfo: TGUID
= IID_IHTTPClientConnectionI
GUID_IHTTPClientConnectionParam: TGUID
= IID_IHTTPClientConnectionP
GUID_IHTTPClientConnection: TGUID
= IID_IHTTPClientC
GUID_IHTTPClientConnectionEvent: TGUID
= IID_IHTTPClientConnectionE
GUID_IHttpClientConnectionFactory
= IID_IHttpClientConnectionFtype
IHttpClientConnectionParam = interface
['{0FA49A71-48BF-40CD-9D77-63B233C4F717}']
function TcpParam: ITcpConnectionP
function GetMethod: PAnsiC
function GetPathAndParams: PAnsiC
function GetAgent: PAnsiC
function GetHeader: PAnsiC
function GetData: PAnsiC
function GetUserName: PAnsiC
function GetPassword: PAnsiC
procedure SetValue(const ServerAddr: PAnsiC const ServerPort: I const UserName, Password, Method, PathAndParams, Agent, Header, Data: PAnsiChar);
IHTTPClientConnectionInfo = interface(ITcpConnectionInfo)
['{24C3D6BF-EC3D-4783-AD98-A5C6E4F24F19}']
function Auth: PAnsiC
IHTTPClientConnection = interface;
IHTTPClientConnectionEvent=interface
['{2FB0AC19--B105-EBC}']
procedure OnHeader(const Http:IHTTPClientC const Header:P const HeaderLenght:NativeInt);
procedure OnStartReceiveContent(const Http:IHTTPClientC const ContentLength:NativeInt);
procedure OnReceiveProgress(const Http:IHTTPClientC const ContentLenght, ContentReceived:NativeInt);
procedure OnError(const Http:IHTTPClientC const ErrStr:PAnsiChar);
THttpClientConnectionEvent = (heHeader, heStartReceiveContent, heReceiveProgress, heError);
IHTTPClientConnection = interface
[IID_IHTTPClientConnection]
function Connect: B
function Info: IHTTPClientConnectionI
function TcpConnection: ITcpC
function DataConnection: IC
function Param:IHttpClientConnectionP
IHttpClientConnectionFactory = interface
[IID_IHttpClientConnectionFactory]
procedure CreateHttpClient(out Conn: IHTTPClientConnection);
procedure DestroyHttpClient(var aClient);
end;implementationend.调用prjHttp.DLL的Delphi工程可以包含下面的单元以及上面的接口单元utHttpInterface.pas即可将utHttpDLL.pas中的 //{$define utHttpDLL)去掉注释,即可以将http客户端这些代码包含到Delphi工程中。unit utHttpDLL;//{$define utHttpDLL}interfaceuses utConnectionInterface, utBaseIvar
HttpClientFactory: IHttpClientConnectionFimplementation{$ifdef utHttpDLL}uses Windows, SysUconst
DLLName = 'prjHttp.DLL';type
Proc = function: IIvar
LibHandle: THfunction GetHttpClientFactory: IHttpClientConnectionFbegin
Result := HttpClientFend;procedure Ivar
LibHandle := SafeLoadLibrary(DLLName);
if LibHandle && INVALID_HANDLE_VALUE then
:= GetProcAddress(LibHandle, 'GetHttpClientFactory');
if Assigned(P) then
HttpClientFactory := IHttpClientConnectionFactory(P);
raise Exception.Create('无法打开库文件' + DLLName);
if not Assigned(HttpClientFactory) then
raise Exception.Create(DLLName + '找不到指定函数');end;procedure Dbegin
if LibHandle && INVALID_HANDLE_VALUE then
FreeLibrary(LibHandle);
Pointer(HttpClientFactory)
:= nil;end;{$else}uses utHttpCprocedure Ibegin
HttpClientFactory:= GetHttpClientFend;procedure Dbegin
Pointer(HttpClientFactory):=nil;end;{$endif}initializationIfinalizationDend.2.DLL中输出接口对象的生命周期管理Delphi对接口采用引用计数的方法管理对象生命周期,但是DLL中输出的对象可能不是被Delphi调用,其引用计数不一定正确,因此DLL中接口对象的生命周期不由Delphi编译器自动生成的代码管理,而是程序员自己控制,所以上面的工厂包括构造和解析两个接口对象的生命周期管理方法。所有接口对象应该集成自下面的接口,而不应该继承自Delphi自带的TInterfacedObject:
TIntObject = class(TObject, IInterface)
function QueryInterface(const IID: TGUID; out Obj): HR stdcall;
function _AddRef: I stdcall;
function _Release: I stdcall;
end;function TIntObject.QueryInterface(const IID: TGUID; out Obj): HRbegin
if GetInterface(IID, Obj) then
Result := 0
Result := E_NOINTERFACE;end;function TIntObject._AddRef: Ibegin
Result := -1;end;function TIntObject._Release: Ibegin
Result := -1end;3.自管理接口对象在Delphi调用注意事项1)接口赋值  错误代码:(Delphi编译器产生代码会先判断接口指针是否为nil,如果非nil自动调用接口的_Release方法)
var P1:IHttpServer。。。。。。。。。。。。  
P1:=FServer.P    P1.SetValue(PWideChar(aName), PAnsiChar(AnsiString(ServerAddr)), ServerPort, 10000, 10,0, 40000);    建议代码:
var P1:IHttpServer................
Pointer(P1):=nil;  
P1:=FServer.P
//如果赋值前P1不是nil,程序会线调用P1._Release后再赋值  2)局部接口变量  错误代码:constructor TTcpServerSplitter.Create(aName:S ServerAddr: S ServerPort: I
RemoteAddr: S RemotePort: Integer);var
Service:IInterfaceO
P1:ITcpConnectionServerP
P2:ITcpConnectionPbegin
inherited C
FServerEvent:=TTcpConnectionServerEventAdapter.Create(Self as ITcpConnectionServerEvent);
FTcpConnectionEvent:=TTcpConnectionEventAdapter.Create(Self as ITcpConnectionEvent);
FConnectionEvent:=TConnectionEventAdapter.Create(Self as IConnectionEvent);
TcpServerFactory.CreateTcpConnectionServer(FServer);
P1:=FServer.P
P1.SetValue(PWideChar(aName), PAnsiChar(AnsiString(ServerAddr)), ServerPort, 10000, 10,0, 40000);
RegistObserver(FServer, FServerEvent);
TcpClientFactory.CreateTcpConnection(FRemote);
P2:=FRemote.P
P2.SetValue(PAnsiChar(AnsiString(RemoteAddr)), RemotePort, Self);
RegistObserver(FRemote,FTcpConnectionEvent);end;上面代码中运行退出后,Delphi编译器会在此代码后面自动调用P1._R P2._Release,  建议代码:constructor TTcpServerSplitter.Create(aName:S ServerAddr: S ServerPort: I
RemoteAddr: S RemotePort: Integer);var
Service:IInterfaceO
P1:ITcpConnectionServerP
P2:ITcpConnectionPbegin
inherited C
FServerEvent:=TTcpConnectionServerEventAdapter.Create(Self as ITcpConnectionServerEvent);
FTcpConnectionEvent:=TTcpConnectionEventAdapter.Create(Self as ITcpConnectionEvent);
FConnectionEvent:=TConnectionEventAdapter.Create(Self as IConnectionEvent);
TcpServerFactory.CreateTcpConnectionServer(FServer);
P1:=FServer.P
P1.SetValue(PWideChar(aName), PAnsiChar(AnsiString(ServerAddr)), ServerPort, 10000, 10,0, 40000);
RegistObserver(FServer, FServerEvent);
TcpClientFactory.CreateTcpConnection(FRemote);
P2:=FRemote.P
P2.SetValue(PAnsiChar(AnsiString(RemoteAddr)), RemotePort, Self);
RegistObserver(FRemote,FTcpConnectionEvent);
Pointer(P1):=
Pointer(P2):=end;&3)函数返回值为接口指针如下面的示例中FServer.Param定义为function THttpServer.Param:IHttpServerParam,返回的是接口类型,下面的代码直接调用Param.SetValue方法:constructor TTcpServerSplitter.Create(aName:S ServerAddr: S ServerPort: I
RemoteAddr: S RemotePort: Integer);var
Service:IInterfaceO
P1:ITcpConnectionServerP
P2:ITcpConnectionPbegin
inherited C
FServerEvent:=TTcpConnectionServerEventAdapter.Create(Self as ITcpConnectionServerEvent);
FTcpConnectionEvent:=TTcpConnectionEventAdapter.Create(Self as ITcpConnectionEvent);
FConnectionEvent:=TConnectionEventAdapter.Create(Self as IConnectionEvent);
TcpServerFactory.CreateTcpConnectionServer(FServer);
FServer.Param.SetValue(PWideChar(aName), PAnsiChar(AnsiString(ServerAddr)), ServerPort, 1, 40000);
RegistObserver(FServer, FServerEvent);
TcpClientFactory.CreateTcpConnection(FRemote);
FRemote.Param.SetValue(PAnsiChar(AnsiString(RemoteAddr)), RemotePort, Self);
RegistObserver(FRemote,FTcpConnectionEvent);end;&上面的代码,Delphi编译器会自动生成两个接口变量,保存FServer.Param和FRemote.Param,由于FServer和FRemote为TTcpServerSplitter对象的全局变量,所以接口在TTcpServerSplitter对象释放时,被调用_Release将导致内存访问异常。constructor TTcpServerSplitter.Create(aName:S ServerAddr: S ServerPort: I
RemoteAddr: S RemotePort: Integer);var
Service:IInterfaceO
P1:ITcpConnectionServerP
P2:ITcpConnectionPbegin
inherited C
FServerEvent:=TTcpConnectionServerEventAdapter.Create(Self as ITcpConnectionServerEvent);
FTcpConnectionEvent:=TTcpConnectionEventAdapter.Create(Self as ITcpConnectionEvent);
FConnectionEvent:=TConnectionEventAdapter.Create(Self as IConnectionEvent);
TcpServerFactory.CreateTcpConnectionServer(FServer);
P1:=FServer.P
P1.SetValue(PWideChar(aName), PAnsiChar(AnsiString(ServerAddr)), ServerPort, 1, 40000);
RegistObserver(FServer, FServerEvent);
TcpClientFactory.CreateTcpConnection(FRemote);
P2:=FRemote.P
P2.SetValue(PAnsiChar(AnsiString(RemoteAddr)), RemotePort, Self);
RegistObserver(FRemote,FTcpConnectionEvent);
Pointer(P1):=
Pointer(P2):= end;4)对象中的接口变量,在对象释放时,需要将接口变量清空。destructor TTcpServerSplitter.Dbegin
Pointer(FServer):=
Pointer(FRemote):=
inherited;end;&&

我要回帖

更多关于 通常所说的血型是指 的文章

 

随机推荐