使用 C 创建解析器

开始之前

可装入实现库或 LIL 是 C 解析器(或节点)的实现模块。LIL 是不用 .dll 扩展名而是采用 .lil 扩展名的 Linux 或 UNIX 的共享对象或 Windows 动态链接库(DLL)。

必须由开发者写的实施函数在C 解析器实施函数中列出。WebSphere Message Broker 提供的用于帮助此过程的实用程序函数在C 解析器实用程序函数中列出。

WebSphere Message Broker 提供样本用户定义的解析器的源代码,它称为 BipSampPluginParser.c。这是一个简单的伪 XML 解析器,您可以使用当前状态的该解析器也可以修改该解析器。

根据要进行解析的位流的复杂程度,解析器的编写步骤也大不相同。此处只描述了基本步骤。下面几节有对它们的讲述:
  1. 声明和定义解析器
  2. 创建解析器的实例
  3. 删除解析器的实例

声明和定义解析器

要向代理声明和定义用户定义的解析器,必须将初始化函数 bipGetParserFactory 包含在 LIL 中。以下步骤简要说明了代理如何调用您的初始化函数,以及该初始化函数如何声明和定义用户定义的解析器:

以下过程告诉您如何向代理声明和定义解析器:

  1. 初始化函数 bipGetParserFactory 是在操作系统已经装入 LIL 并且初始化后,由代理调用的。代理调用此函数以了解您的 LIL 能做些什么,以及代理应该如何调用 LIL。例如:
    CciFactory LilFactoryExportPrefix * LilFactoryExportSuffix
    bipGetParserFactory()
  2. 然后,bipGetParserFactory 函数必须调用实用程序函数 cpiCreateParserFactory。此函数传递回您的 LIL 支持的所有解析器的唯一工厂名(或组名)。在代理的所有 LIL 中,每个传递回的工厂名(或组名)都必须是唯一的。
  3. 然后,LIL 必须调用实用程序函数 cpiDefineParserClass 以传递每个解析器的唯一名称和实施函数地址的虚函数表。
    例如,以下代码声明并定义了一个名为 InputxParser 的解析器:
    {
    	CciFactory* factoryObject;
      int                rc = 0;
    CciChar factoryName[] = L"MyParserFactory";
    	CCI_EXCEPTION_ST exception_st;
    
    /* Create the Parser Factory for this parser */
    factoryObject = cpiCreateParserFactory(0, factoryName);
    	if (factoryObject == CCI_NULL_ADDR) {
    		
    			/* Any local error handling can go here */
    	}
    	else {
    /* Define the parsers supported by this factory */
    static CNI_VFT vftable = {CNI_VFT_DEFAULT};
    
      /* Setup function table with pointers to parser implementation functions */
      vftable.iFpCreateContext            = cpiCreateContext;
      vftable.iFpParseBufferEncoded       = cpiParseBufferEncoded;
      vftable.iFpParseFirstChild          = cpiParseFirstChild;
      vftable.iFpParseLastChild           = cpiParseLastChild;
      vftable.iFpParsePreviousSibling     = cpiParsePreviousSibling;
      vftable.iFpParseNextSibling         = cpiParseNextSibling;
      vftable.iFpWriteBufferEncoded       = cpiWriteBufferEncoded;
      vftable.iFpDeleteContext            = cpiDeleteContext;
      vftable.iFpSetElementValue          = cpiSetElementValue;
      vftable.iFpElementValue             = cpiElementValue;
      vftable.iFpNextParserClassName      = cpiNextParserClassName;
      vftable.iFpSetNextParserClassName   = cpiSetNextParserClassName;
      vftable.iFpNextParserEncoding       = cpiNextParserEncoding;
    vftable.iFpNextParserCodedCharSetId = cpiNextParserCodedCharSetId;
    
    cpiDefineParserClass(0, factoryObject, L"InputxParser", &vftable);
    	}
    
      /* Return address of this factory object to the broker */
    	return(factoryObject);
    }

    然后,初始化函数必须通过调用 cpiCreateParserFactory 创建解析器工厂。工厂支持的解析器类通过调用 cpiDefineParserClass 来定义。工厂对象的地址(由 cpiCreateParserFactory 返回)必须作为来自初始化函数的返回值返回到代理。

    例如:
    1. 使用 cpiCreateParserFactory 函数创建解析器工厂:
        factoryObject = cpiCreateParserFactory(&rc, constParserFactory);
        
    2. 使用 cpiDefineParserClass 函数定义工厂支持的消息的类:
      if (factoryObject) {
            cpiDefineParserClass(&rc, factoryObject, constPXML, &vftable);
        }
      else {
              /* Error: Unable to create parser factory */
        }
    3. 向代理返回此工厂对象的地址:
        	return(factoryObject);
      }

创建解析器的实例

以下过程向您显示了如何实例化您的解析器:

当代理接收到函数指针的表,它为每个用户定义的解析器的实例化调用函数 cpiCreateContext。如果您有三个使用您的用户定义的解析器的消息流,将为每个消息流调用您的 cpiCreateContext 函数。此函数应该为用户定义的解析器的实例化分配内存,以保留已配置属性的值。例如:
  1. 调用 cpiCreateContext 函数:
    CciContext* _createContext(
        CciFactory* factoryObject,
      CciChar* parserName,
      CciNode* parserObject
    ){
      static char* functionName = (char *)"_createContext()";
      PARSER_CONTEXT_ST* p;
        CciChar          buffer[256];
  2. 为本地上下文分配一个指针并清除上下文区域:
      p = (PARSER_CONTEXT_ST *)malloc(sizeof(PARSER_CONTEXT_ST));
    
      if (p) {
              memset(p, 0, sizeof(PARSER_CONTEXT_ST));
  3. 保存上下文中的解析器对象指针:
       p->parserObject = parserObject;
  4. 保存解析器名称:
     CciCharNCpy((CciChar*)&p->parserName, parserName, MAX_NODE_NAME_LEN);
  5. 返回解析器上下文:
    return (CciContext*) p;

删除解析器的实例

当消息流被删除或重新部署时,或当执行组进程被停止时(使用 mqsistop 命令),解析器被破坏。 当解析器被破坏时,它应该释放任何已使用的内存并释放任何占用的资源。您使用 cpiDeleteContext 函数来这样做。 例如:

void cpiDeleteContext(
    CciParser*  parser,
    CciContext* context
){
    PARSER_CONTEXT_ST* pc = (PARSER_CONTEXT_ST *)context ;
    int                rc = 0;

    return;
}
声明 | 商标 | 下载 | 书库 | 支持 | 反馈
Copyright IBM Corporation 1999, 2006 最后一次更新时间:2006/08/14
as10010_