请问如何在客户端调用应用服务器接口?大侠请进,help

cuptbluesky 2003-01-20 12:03:21
在应用服务器上定义了一个接口,但怎么在客户端调用应用服务器地接口呢?在帮助上是这样说的:“当扩展应用程序服务器接口时,需要一种使用由连接组件创建的连接来调用所有的扩展的方法,这可以使用连接组件的AppServer属性来完成。AppServer是表示应用程序服务器接口的变量。要调用这个接口,必须从该变量中得到一个分派的接口,这个分派的接口与在创建远程数据模块时创建的接口具有相同的名字,但在后面加上字符串‘Disp’”(这个分派的接口在通过类库编辑器产生的_TLB.h文件中声明)
下面是客户端提交时的代码:
OleVariant CustVar;
ClientDataSet1->CheckBrowseMode();
if(ClientDataSet1->ChangeCount>0)
CustVar=ClientDataSet1->Delta;
else
CustVar.ChangeType(VT_NULL);
try
{
IFinalKingDisp srvr;//远程数据模块FinalKing
srvr.Bind(LPDISPATCH(SocketConnection1->AppServer));
srvr.ApplyUpdates(reinterpret_cast<VARIANTOBJ*>(&CustVar));
ShowMessage("已经正确地录入数据库中!");

}
catch(Exception & exception)
{
Application->ShowException( & exception) ;
}
编译时报错:Undefined ymbol 'IFinalKingDisp'
‘使用连接组件的AppServer属性来完成’这话怎么理解?从出错信息看,好像AppServer没起作用,客户端根本找不到应用程序服务器上的相关定义,可是
不使用扩展接口时,程序运行正常。
下面是E文help:
Applications do not need to call the IAppServer interface directly because the appropriate calls are made automatically when you use the properties and methods of the client dataset. However, while it is not necessary to work directly with the IAppServer interface, if you are not using SOAP you may have added your own extensions to the application server抯 interface. When you extend the application server抯 interface, you need a way to call those extensions using the connection created by your connection component. You can do this using the AppServer property of the connection component. AppServer is a Variant that represents the application server抯 interface. To call this interface, you must obtain a dispatch interface from this Variant. The dispatch interface has the same name as the interface that was created when youcreated the remote data module, but with the string 揇isp?appended. Thus, if your remote data module is called MyAppServer, you can use AppServer to call its interface as follows:

IDispatch* disp = (IDispatch*)(MyConnection->AppServer)

IMyAppServerDisp TempInterface( (IMyAppServer*)disp);
TempInterface.SpecialMethod(x,y);

Note: The dispatch interface is declared in the _TLB.h file generated by the Type Library editor.

If you are using SOAP, you can抰 use the AppServer property. Instead, you must use a remote interfaced object (THTTPRio) and make early-bound calls. As with all early-bound calls, the client application must know the application server抯 interface declaration at compile time. You can add this to your client application by referencing a WSDL document that describes the interface you want to call. Note that for SOAP servers, this interface is entirely separate from the SOAP data module抯 interface. For information on importing a WSDL document that describes the interface, see Importing WSDL documents.

Note: The unit that declares the server interface must also register it with the invocation registry. For details on how to register invokable interfaces, see Understanding invokable interfaces.

Once you have imported a WSDL document to generate a unit declaring and registering the interface, create an instance of THTTPRio for the desired interface:

THTTPRio *X = new THTTPRio(NULL);

Next, assign the URL that your connection component uses to the remote interfaced object, appending the name of the interface you want to call:

X->URL = SoapConnection1.URL + "IMyInterface";

Now, you can use the QueryInterface method to obtain an interface to call the server抯 methods:

InterfaceVariable = X->QueryInterface(IMyInterfaceIntf);

if (InterfaceVariable)
{
InterfaceVariable->SpecialMethod(a,b);
}

Note that the call to QueryInterface takes as an argument the DelphiInterface wrapper for the invokable interface rather than the invokable interface itself.
...全文
262 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
cuptbluesky 2003-02-18
  • 打赏
  • 举报
回复
谢谢,猛禽兄
猛禽 2003-02-18
  • 打赏
  • 举报
回复
基本上多表一条记录的更新是通过中间层方法,单表多条记录通过数据集。
多表多记录的情况倒没碰过^_^
cuptbluesky 2003-02-18
  • 打赏
  • 举报
回复
谢谢猛禽兄,一般你们做三层时,对数据集的修改和提交是怎么做的?能够举个例子看看?让小弟长长见识
猛禽 2003-02-17
  • 打赏
  • 举报
回复
一般来说,一个合理的设计,这样的动作通常会被定义成一个操作(operator),对应的就是中间层里的一个方法(method),只要将操作所需要的条件以参数的形式传入,在中间层里操作具体的数据集,而不是在客户端操作数据集,再将数据集的变化传到中间层。
cuptbluesky 2003-02-12
  • 打赏
  • 举报
回复
猛禽兄,但如果对多个数据集进行操作的话,使用ClientDataSet->ApplyUpdates是不行的吧,对多个数据集进行操作一般都把方法定义在服务器端,通过客户端调用服务器的方法来进行,可是我这样做,出的毛病就是不能解决,不知我说错了没,请指教,又或者大哥有更好的办法,小弟洗耳恭听,学习,请:
猛禽 2003-02-11
  • 打赏
  • 举报
回复
我又看了一下,发现你的操作跟ClientDataSet->ApplyUpdates一样嘛,何必这样自找麻烦呢?
cuptbluesky 2003-01-27
  • 打赏
  • 举报
回复
// *********************************************************************//
// SmartIntf: TCOMIFinalKing
// Interface: IFinalKing
// *********************************************************************//
template <class T /* IFinalKing */ >
class TCOMIFinalKingT : public TComInterface<IFinalKing>, public TComInterfaceBase<IUnknown>
{
public:
TCOMIFinalKingT() {}
TCOMIFinalKingT(IFinalKing *intf, bool addRef = false) : TComInterface<IFinalKing>(intf, addRef) {}
TCOMIFinalKingT(const TCOMIFinalKingT& src) : TComInterface<IFinalKing>(src) {}
TCOMIFinalKingT& operator=(const TCOMIFinalKingT& src) { Bind(src, true); return *this;}

HRESULT __fastcall ApplyUpdates(VARIANT* CustVar/*[in]*/);

};
typedef TCOMIFinalKingT<IFinalKing> TCOMIFinalKing;

// *********************************************************************//
// DispIntf: IFinalKing
// Flags: (4416) Dual OleAutomation Dispatchable
// GUID: {8B9CF555-3071-4A36-A740-98F00E2A2C3A}
// *********************************************************************//
template<class T>
class IFinalKingDispT : public TAutoDriver<IFinalKing>
{
public:
IFinalKingDispT(){}

IFinalKingDispT(IFinalKing *pintf)
{
TAutoDriver<IFinalKing>::Bind(pintf, false);
}

IFinalKingDispT(IFinalKingPtr pintf)
{
TAutoDriver<IFinalKing>::Bind(pintf, true);
}

IFinalKingDispT& operator=(IFinalKing *pintf)
{
TAutoDriver<IFinalKing>::Bind(pintf, false);
return *this;
}

IFinalKingDispT& operator=(IFinalKingPtr pintf)
{
TAutoDriver<IFinalKing>::Bind(pintf, true);
return *this;
}

HRESULT BindDefault()
{
return OLECHECK(Bind(CLSID_FinalKing));
}

HRESULT BindRunning()
{
return BindToActive(CLSID_FinalKing);
}

HRESULT __fastcall ApplyUpdates(VARIANT* CustVar/*[in]*/);
HRESULT __fastcall AS_ApplyUpdates(BSTR ProviderName/*[in]*/, VARIANT Delta/*[in]*/,
long MaxErrors/*[in]*/, long* ErrorCount/*[out]*/,
VARIANT* OwnerData/*[in,out]*/,
VARIANT* Value/*[out,retval]*/);
VARIANT __fastcall AS_ApplyUpdates(BSTR ProviderName/*[in]*/, VARIANT Delta/*[in]*/,
long MaxErrors/*[in]*/, long* ErrorCount/*[out]*/,
VARIANT* OwnerData/*[in,out]*/);
HRESULT __fastcall AS_GetRecords(BSTR ProviderName/*[in]*/, long Count/*[in]*/,
long* RecsOut/*[out]*/, long Options/*[in]*/,
BSTR CommandText/*[in]*/, VARIANT* Params/*[in,out]*/,
VARIANT* OwnerData/*[in,out]*/,
VARIANT* Value/*[out,retval]*/);
VARIANT __fastcall AS_GetRecords(BSTR ProviderName/*[in]*/, long Count/*[in]*/,
long* RecsOut/*[out]*/, long Options/*[in]*/,
BSTR CommandText/*[in]*/, VARIANT* Params/*[in,out]*/,
VARIANT* OwnerData/*[in,out]*/);
HRESULT __fastcall AS_DataRequest(BSTR ProviderName/*[in]*/, VARIANT Data/*[in]*/,
VARIANT* Value/*[out,retval]*/);
VARIANT __fastcall AS_DataRequest(BSTR ProviderName/*[in]*/, VARIANT Data/*[in]*/);
HRESULT __fastcall AS_GetProviderNames(VARIANT* Value/*[out,retval]*/);
VARIANT __fastcall AS_GetProviderNames(void);
HRESULT __fastcall AS_GetParams(BSTR ProviderName/*[in]*/, VARIANT* OwnerData/*[in,out]*/
, VARIANT* Value/*[out,retval]*/);
VARIANT __fastcall AS_GetParams(BSTR ProviderName/*[in]*/, VARIANT* OwnerData/*[in,out]*/);
HRESULT __fastcall AS_RowRequest(BSTR ProviderName/*[in]*/, VARIANT Row/*[in]*/,
long RequestType/*[in]*/, VARIANT* OwnerData/*[in,out]*/
, VARIANT* Value/*[out,retval]*/);
VARIANT __fastcall AS_RowRequest(BSTR ProviderName/*[in]*/, VARIANT Row/*[in]*/,
long RequestType/*[in]*/, VARIANT* OwnerData/*[in,out]*/);
HRESULT __fastcall AS_Execute(BSTR ProviderName/*[in]*/, BSTR CommandText/*[in]*/,
VARIANT* Params/*[in,out]*/, VARIANT* OwnerData/*[in,out]*/);


};
typedef IFinalKingDispT<IFinalKing> IFinalKingDisp;
cuptbluesky 2003-01-27
  • 打赏
  • 举报
回复
#include "databkr.hpp"

using Midas::IAppServer;

// *********************************************************************//
// Forward reference of some VCL types (to avoid including STDVCL.HPP)
// *********************************************************************//
namespace Stdvcl {class IStrings; class IStringsDisp;}
using namespace Stdvcl;
typedef TComInterface<IStrings> IStringsPtr;
typedef TComInterface<IStringsDisp> IStringsDispPtr;

namespace Applicationserver_tlb
{

// *********************************************************************//
// HelpString: ApplicationServer Library
// Version: 1.0
// *********************************************************************//


// *********************************************************************//
// GUIDS declared in the TypeLibrary. Following prefixes are used:
// Type Libraries : LIBID_xxxx
// CoClasses : CLSID_xxxx
// DISPInterfaces : DIID_xxxx
// Non-DISP interfaces: IID_xxxx
// *********************************************************************//
extern "C" const __declspec(selectany) GUID LIBID_ApplicationServer = {0xC7F18AA0, 0xEC28, 0x4286,{ 0x96, 0xFC, 0xA9,0xB5, 0x09, 0xAA,0x65, 0xDD} };
extern "C" const __declspec(selectany) GUID IID_IFinalKing = {0x8B9CF555, 0x3071, 0x4A36,{ 0xA7, 0x40, 0x98,0xF0, 0x0E, 0x2A,0x2C, 0x3A} };
extern "C" const __declspec(selectany) GUID CLSID_FinalKing = {0x872C1787, 0x261B, 0x40E0,{ 0x9F, 0xE8, 0x71,0xFF, 0x37, 0x66,0x95, 0xEB} };

// *********************************************************************//
// Forward declaration of types defined in TypeLibrary
// *********************************************************************//
interface DECLSPEC_UUID("{8B9CF555-3071-4A36-A740-98F00E2A2C3A}") IFinalKing;
typedef TComInterface<IFinalKing, &IID_IFinalKing> IFinalKingPtr;


// *********************************************************************//
// Declaration of CoClasses defined in Type Library
// (NOTE: Here we map each CoClass to its Default Interface)
//
// The LIBID_OF_ macro(s) map a LIBID_OF_CoClassName to the GUID of this
// TypeLibrary. It simplifies the updating of macros when CoClass name
// change.
// *********************************************************************//

#define LIBID_OF_FinalKing (&LIBID_ApplicationServer)
// *********************************************************************//
// Interface: IFinalKing
// Flags: (4416) Dual OleAutomation Dispatchable
// GUID: {8B9CF555-3071-4A36-A740-98F00E2A2C3A}
// *********************************************************************//
interface IFinalKing : public IAppServer
{
public:
virtual HRESULT STDMETHODCALLTYPE ApplyUpdates(VARIANT* CustVar/*[in]*/) = 0; // [1]

#if !defined(__TLB_NO_INTERFACE_WRAPPERS)



#endif // __TLB_NO_INTERFACE_WRAPPERS

};

#if !defined(__TLB_NO_INTERFACE_WRAPPERS)
cuptbluesky 2003-01-27
  • 打赏
  • 举报
回复
好的,下面就是XXX_TLB.h
// ************************************************************************ //
// WARNING
// -------
// The types declared in this file were generated from data read from a
// Type Library. If this type library is explicitly or indirectly (via
// another type library referring to this type library) re-imported, or the
// 'Refresh' command of the Type Library Editor activated while editing the
// Type Library, the contents of this file will be regenerated and all
// manual modifications will be lost.
// ************************************************************************ //

// C++ TLBWRTR : $Revision: 1.151.1.0.1.27 $
// File generated on 2003-1-21 23:05:41 from Type Library described below.

// ************************************************************************ //
// Type Lib: D:\RemoteTest\ApplicationServer.tlb (1)
// LIBID: {C7F18AA0-EC28-4286-96FC-A9B509AA65DD}
// LCID: 0
// Helpfile:
// HelpString: ApplicationServer Library
// DepndLst:
// (1) v1.0 Midas, (C:\WINNT\System32\midas.dll)
// (2) v2.0 stdole, (C:\WINNT\System32\stdole2.tlb)
// ************************************************************************ //
#ifndef ApplicationServer_TLBH
#define ApplicationServer_TLBH

#pragma option push -b -w-inl

#include <utilcls.h>
#if !defined(__UTILCLS_H_VERSION) || (__UTILCLS_H_VERSION < 0x0600)
//
// The code generated by the TLIBIMP utility or the Import|TypeLibrary
// and Import|ActiveX feature of C++Builder rely on specific versions of
// the header file UTILCLS.H found in the INCLUDE\VCL directory. If an
// older version of the file is detected, you probably need an update/patch.
//
#error "This file requires a newer version of the header UTILCLS.H" \
"You need to apply an update/patch to your copy of C++Builder"
#endif
#include <olectl.h>
#include <ocidl.h>
#if defined(USING_ATLVCL) || defined(USING_ATL)
#if !defined(__TLB_NO_EVENT_WRAPPERS)
#include <atl/atlmod.h>
#endif
#endif
猛禽 2003-01-27
  • 打赏
  • 举报
回复
你那个FinalKing的接口是你自己另加的还是RDM的默认接口,看不出来啊,你把xxx_TLB.h贴出来看看
cuptbluesky 2003-01-25
  • 打赏
  • 举报
回复
谢谢猛禽兄,请问如果不外加接口,对多个数据集进行处理时怎么做?三层我还是菜鸟,要多向猛禽兄学习,猛禽兄可否把不外加接口而在RDM的接口里实现给我讲解一下具体的做法,我查了好多资料都没有我那种问题的解答,郁闷,也许是该换思路了.
猛禽 2003-01-25
  • 打赏
  • 举报
回复
TO:cuptbluesky (苦行僧)
这几天在学习?怎么也没人来顶啊?这个方法好像蛮麻烦的,你还是把功能放在RDM的接口里实现吧,不要外加接口就简单多了。
cuptbluesky 2003-01-23
  • 打赏
  • 举报
回复
企鹅兄,猛禽兄请指点迷津吧,谢谢!
猛禽 2003-01-23
  • 打赏
  • 举报
回复
你那段帮助后面一段是说SOAP的,我就没看了,看了前面一段,它的意思可能跟你想要的功能不同吧?
它指的是这样的扩展:
interface IRDMTest : public IAppServer
即指你自己的RemoteDataModule(它本身是从IAppServer接口扩展而来),而看样子,你想要的是在此之外,再增加一个如IMyTest这样的接口,默认情况下,它是从IDispatch派生,如:
interface IMyTest : public IDispatch
它与IRDMTest/IAppServer都没有关系,但Connection(DCOM/Socket)都只支持IAppServer接口的扩展,所以你用这样简单的做法在客户端是无法取得IMyTest,当然会出错了。
据我所知,在COM里要通过一个接口访问多个接口的途径是包容或聚合,具体可以参见《COM技术内幕》一书的第八章。^_^
具体实现要看我能不能抽出时间来帮你做了。你最好看看书自已做做看。^_^
cuptbluesky 2003-01-23
  • 打赏
  • 举报
回复
谢谢,等你的好消息,I think u can
猛禽 2003-01-23
  • 打赏
  • 举报
回复
研究中……
RomanticProgrammer 2003-01-21
  • 打赏
  • 举报
回复
你用的是SocketConnection还是DCOMConnection?
如果你的客户端和服务端不在同一台计算机上,你在客户端注册应用程序服务器的lib文件了吗?
////////////////////////////
看看这个帖子:

http://expert.csdn.net/Expert/topic/1183/1183521.xml?temp=.2863733
cuptbluesky 2003-01-21
  • 打赏
  • 举报
回复
Invalid,兰企鹅,TR,warton,pazee,raptor他们呢?帮帮我看看
cuptbluesky 2003-01-21
  • 打赏
  • 举报
回复
回兰企鹅,thx,anyway
我用的是SocketConnection,我的客户端和服务器不在同一台机子上的话,怎样注册应用程序服务器的lib文件呢?
我使用了你们帖子上的方法,编译是通过了,可是提交时还是会出现下列提示:
IsBound() @ C:\program files\borland\cbuilder6\include\vcl
\utilcls.h/4270 Press[Y]es to terminate,[N]o to continue and
[C]ancel to Debug
然后程序中止,请教一下这又该怎么处理呢?
服务器端:

STDMETHODIMP TFinalKingImpl::ApplyUpdates(VARIANT* CustVar)
{
int ErrCount=0;
m_DataModule->DatabaseAppServer->StartTransaction();
try
{
OleVariant & vCustVar = *(reinterpret_cast<OleVariant *>(CustVar));
//判断前台传来的DataSet是否有被更改
//如果有,则把更改部分录入数据库中
if(!vCustVar.IsNull())
{
ErrCount=0;
m_DataModule->DataSetProviderQuery->ApplyUpdates(vCustVar,0,ErrCount,vCustVar);
if(ErrCount>0)
Error("Error in ApplyUpdates",IID_IFinalKing);
}
//确认刚才的录入操作
m_DataModule->DatabaseAppServer->Commit();
}
catch(Exception &e)
{
//恢复到录入前的状态
m_DataModule->DatabaseAppServer->Rollback();
return Error(e.Message.c_str(),IID_IFinalKing);
}
return S_OK;
}
客户端:
void __fastcall TForm1::BtnPostClick(TObject *Sender)
{
OleVariant CustVar;
ClientDataSet1->CheckBrowseMode();
if(ClientDataSet1->ChangeCount>0)
CustVar=ClientDataSet1->Delta;
else
CustVar.ChangeType(VT_NULL);
try
{

IFinalKingDisp srvr;
srvr.Bind(LPDISPATCH(SocketConnection1->AppServer));
//srvr.Bind((IDispatch*)SocketConnection1->AppServer);
srvr.ApplyUpdates(reinterpret_cast<VARIANTOBJ*>(&CustVar));
ShowMessage("已经正确地录入数据库中!");
srvr.Unbind();
}
catch(Exception & exception)
{
Application->ShowException( & exception) ;
}

}
halibut 2003-01-20
  • 打赏
  • 举报
回复
不会,帮你UP!学习!蹭点分!呵呵~~
加载更多回复(2)

1,317

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder 网络及通讯开发
社区管理员
  • 网络及通讯开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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