使用 C API


介绍

实例代码

向 API 调用传送结构

释放内存


介绍

本文档讲述对应用程序服务器 C API 调用的处理。下面一节包含调用 InquireRequests API 函数的必需步骤的实例代码(Application.cpp)。


实例代码

Application.cpp 代码

Application.cpp 的下列实例代码是本章中所有 API 实例的基础。 (下列实例建立于该代码上。)

{ long nAPIHandle;
  long nErrorCode;
  Connect( &nAPIHandle, "indy_pp_es1", 8000, "EXAV", NULL, &nErrorCode );
  PROBLEM_RECORD* pProblemList = NULL;
  PROBLEM_FILTER filter;
  InitProblem_Filter( nAPIHandle, &filter );
  filter.system = new char[16];
  strcpy( filter.system, "PC APPLICATIONS" );
  filter.component = new char[13];
  strcpy( filter.component, "WEB BROWSERS" );
  filter.item = new char[9];
  strcpy( filter.item, "NETSCAPE" );
  long max_requested = -1; // no restriction on number to retrieve
  int nResult = InquireRequests( nAPIHandle, &filter, &pProblemList, &max_requested,
      & nErrorCode ); 
  FreeRequestList( nAPIHandle, &pProblemList );
  Disconnect( nAPIHandle ); }

InquireRequests 函数完成后,可以检查返回码,并可以像“传送”其他单链接表一样来传送链接的列表 pProblemList。

if ( nResult == SAI_OK ) 
{ char myBuffer[512]; 
PROBLEM_RECORD* pProblemRecord;
for ( pProblemRecord = pProblemList; pProblemRecord != NULL;
pProblemRecord = pProblemRecord->next ) 
{ sprintf( myBuffer, "%s", pProblemRecord->problem_id );
 ...
 /* do some other processing */
 ...} }

本实例仅使用 PROBLEM_RECORD 和 PROBLEM_FILTER 结构中的少数字段。关于这些结构中的字段和错误代码的完整列表,请参见附录 A。

注:代码实例调用 Connect 和 Disconnect 函数。没有必要也不建议在每次调用函数时都调用这些函数。对于每个应用程序应当只调用它们。


向 API 调用传送结构

概述

在将结构传送给 API 之前,必须对其进行初始化。在前一个实例中,将一个 PROBLEM_FILTER 结构传送给了 InitProblemFilter 函数。

该函数将结构成员设置为缺省值,这是 C++ 为类对象提供构造器的方式。由于 API 可以用于 C++ 和非 C++ 应用程序,所以不可能提供构造器。

Init 函数将 char* 变量缺省为 NULL,将长型变量缺省为 -1,将 TRI_BOOL 变量缺省为 BOOL_UNDEFINED。如果不更改这些变量的缺省值,在将结构发送给应用程序服务器处理时将忽略它们。这样,可以在数据库里支持 NULL 值。

例如,在前一个 PROBLEM_FILTER 结构中,begin_date_range 和 end_date_range 的设置仍然为 NULL,因此可以选择任何日期范围的问题。在 CONTACT_FILTER 中,如果将活动的 TRI_BOOL 成员设置为 BOOL_UNDEFINED,应用程序服务器“不”会过滤出基于活动字段的联系人。关于结构及其数据成员的完整列表,请参见附录 A。

初始化 API

由于 C API 应用程序服务器的内部命令是用 C++ 编写的,所以使用 API 的最重要的步骤是初始化 Connect 函数。该函数创建一个处理 API 调用的内部 APIManager 对象。Connect 建立一个新的 APIManager 实例,并将该对象的地址分配给 pAPIManager 变量。对 API 的进一步调用需要将该已初始化的变量作为第一个参数,以便可以对 APIManager 进行方法调用。

释放 API

在调用的应用程序不再需要使用 API 提供的操作时,它必须调用 Disconnect。在应用程序使用 DLL 的过程中提供在“创建”调用中创建的 APIManager 对象。

注:调用 Disconnect 函数来删除内部 APIManager 是很重要的。这可以避免内存漏洞。

使用扩展数据

将扩展数据传送给 API 调用是通过创建传送给 API 调用的扩展数据对象列表来完成的。下列代码显示如何修改实例 Application.cpp:

{ long nAPIHandle;
long nErrorCode; 
Connect( &nAPIHandle, "indy_pp_es1", 8000, "EXAV", NULL, &nErrorCode ); 
PROBLEM_RECORD* pProblemList = NULL;
PROBLEM_FILTER filter;
EXTENDED_DATA* user_data = NULL; 
InitProblemFilter( nAPIHandle, &filter );
memset( &filter, '\0', sizeof( PROBLEM_FILTER ) ); 
filter.system = new char[16];
strcpy( filter.system, "PC APPLICATIONS" );
filter.component = new char[13];
strcpy( filter.component, "WEB BROWSERS" );
filter.item = new char[9];
strcpy( filter.item, "NETSCAPE" ); 
user_data = new EXTENDED_DATA;
user_data->pszName = new char[15];
strcpy( user_data->pszName, "REQUEST_STATUS" );
user_data->pszValue = new char[9];
strcpy( user_data->pszValue, "INACTIVE" );
user_data->next = NULL; 
long max_requested = -1; // no restriction on number to retrieve
int nResult = InquireRequests( nAPIHandle, &filter, &pProblemList,
    &max_requested, & nErrorCode, user_data ); 
FreeRequestList( nAPIHandle, &pProblemList ); 
Disconnect( nAPIHandle ); }

得到的 pProblemList 具有一个附加成员,用于包含 EXTENDED_DATA 结构列表的各个 PROBLEM_RECORD。对该附加数据的访问类似于:

if ( nResult == SAI_OK )
{ char myBuffer[512];
PROBLEM_RECORD* pProblemRecord;
for ( pProblemRecord = pProblemList;
      pProblemRecord != NULL;
      pProblemRecord = pProblemRecord->next ) 
{ sprintf( myBuffer, "%s", pProblemRecord->problem_id );
...
 /* do some other processing */
...
if ( pProblemList->user_data != NULL ) 
{ EXTENDED_DATA* pExtendedData; 
for ( pExtendedData = pProblemList->user_data;
      pExtendedData != NULL;
      pExtendedData = pExtendedData->next ) 
{ sprintf( myBuffer, 鈥?s鈥? pExtendedData->pszValue );
...
/* do some more processing */
...
} { } }

状态代码

前一个实例显示 API 调用返回状态代码并将其存储在 nResult 的方式。下表列出可能用于 API 调用的状态代码:

定义的名称 错误说明
SAI_OK 0 没有出错。
SAI_ERROR 1 C API 中的普通错误。
SAI_SQL_ERROR 2 发生 SQL 错误。
SAI_CLIENT_ERROR 3 在网络客户机与应用程序服务器通信的过程中发生错误。

在进行 API 调用时,建议对照 SAI_OK 检查状态代码。如果发现错误,请检查错误代码参数(在前一个实例中为 nErrorCode)中的错误号码。如果出现 SQL 错误,请参阅数据库手册中的说明。

注:连接失败 -13 是一个公共客户机错误。


释放内存

概述

其他应用程序不能删除一个应用程序“占用”的内存。对同样是应用程序的 DLL 也一样。由于 C DLL 分配返回调用的应用程序的 PROBLEM_RECORD 列表使用的内存,所以 DLL 必须提供一种让应用程序释放被使用的列表的方法。这通过调用 FreeRequestList 来实现:

FreeRequestList( nAPIHandle, &pProblemList );

FreeRequestList 需要 APIHandle 和作为参数的列表地址。

释放内存的其他函数

除 FreeRequestList 之外,还有几个清除内存的 C API 函数。其中两个是 FreeSolutionList 和 FreeHistoryList。这些函数分别释放 SOLUTION_RECORD 和 HISTORY_RECORD 结构的列表。

注:作为一种预防,在调用 Disconnect 时,API 释放已分配的内存,因此没有必要调用这些函数。

提供释放函数,是为了在执行使用 API 的应用程序而又需要保留内存的情况下提供方便。