【问题标题】:C macro variable MQOD_DEFAULT fails to compile with gcc 4.8C 宏变量 MQOD_DEFAULT 无法使用 gcc 4.8 编译
【发布时间】:2018-03-21 05:43:33
【问题描述】:

我正在尝试在 c++ 类中使用 MQ 系列的 C API 中的几种结构。这是 IBM 的其中一种结构的文档 https://www.ibm.com/support/knowledgecenter/SSFKSJ_7.1.0/com.ibm.mq.doc/fr13840_.htm 问题似乎是宏变量,例如 MQOD_DEFAULT。全局初始化结构时(在任何函数或方法之外)初始化工作。但是在函数或方法中,我收到如下错误:

    no match for >>operator=<< operand types are >>MQOD {aka tagMQOD&)}<< and >>brace-enclosed initializer list><<)

使用 gcc 4.8 可以正常编译:

    MQOD od = {  MQOD_DEFAULT };

在方法内部抛出编译错误 no match for operator=...:

    void MyClass::Methode()
    {
      MQOD od = {  MQOD_DEFAULT };
    }

MQOD_DEFAULT 被 IBM 描述为宏变量:

    #define MQOD_DEFAULT {MQOD_STRUCT_ID_ARRAY},\
                          MQOD_VERSION_1,\
                          MQOT_Q,\
                          {""},\
                          ...
                          ... 

我在 IBM 的开发人员文档(第 77 页)中找到了更多信息:ftp://public.dhe.ibm.com/software/integration/wmq/docs/V7.5/PDFs/wmq75.develop.pdf

要初始化此类结构中的字段,建议使用以下技术:
1. 使用适当的 MQxxx_DEFAULT 宏变量来声明结构的实例
初始化结构。此实例成为其他实例的模型:

MQMD ModelMsgDesc = {MQMD_DEFAULT};                                                               
/* declare model instance */                                                                      

在声明中编码 static 或 auto 关键字以赋予模型实例静态或动态
生命周期,根据需要。
2. 使用 calloc 或 malloc 函数获取结构的动态实例的存储:

   PMQMD   InstancePtr;                                                                                
   InstancePtr = malloc(sizeof(MQMD));                                                               
         /* get storage for dynamic instance */                                                            

3。使用 memcpy 函数将模型实例复制到动态实例中:

    memcpy(InstancePtr,&ModelMsgDesc,sizeof(MQMD));                                                   
         /* initialize dynamic instance */                                                                 

但是 InstancePtr = malloc(sizeof(MQMD));给了我同样的错误“no operator="

解决这个问题的最佳方法是什么?

【问题讨论】:

  • 初始化 (type x = value;) 不同于赋值 (x = value;)。对operator= 的引用表明您正在尝试分配一个“大括号括起来的初始值设定项列表”。就是不行。
  • 您是使用 C++ 还是 C 进行编程?请不要同时使用这两个标签——它们完全不同。
  • 如前所述,我使用 C++ 编程,但使用 IBM 的 MQ C API。我认为这是跨越国界的原因。但我明白你的意思。我将删除 C 标记。
  • @BoPersson 好的,但为什么会有不同的行为?为什么全局初始化时我没有收到该错误?分别为什么我在函数或方法中初始化时会得到它?
  • operator= 不参与初始化,所以你可能没有做你认为你正在做的事情。如果你展示了一些代码......

标签: c++ ibm-mq


【解决方案1】:
MQOD od = {  MQMD_DEFAULT };

哇。你走偏了——我猜湿的时候穿拖鞋!

首先,定义了 MQOD_DEFAULT、MQMD_DEFAULT、MQGMO_DEFAULT、MQPMO_DEFAULT 等。即简单的 C 快捷方式,使程序员免于一遍又一遍地重新输入内容。

其次,您不能(也不应该)将定义用于一个结构并将其用于另一个结构。

MQOD od = {  MQOD_DEFAULT };

MQMD od = {  MQMD_DEFAULT };

但从不

MQOD od = {  MQMD_DEFAULT };

第三,我一直使用“sizeof(MQMD)”。

memcpy(InstancePtr,&ModelMsgDesc,sizeof(MQMD));

和做的一样:

memcpy(InstancePtr,&ModelMsgDesc,sizeof(ModelMsgDesc));

最后,我不相信您收到的错误来自您声称的行。

【讨论】:

  • 非常感谢您的意见。 MQMD_DEFAULT 实际上是一个错字。在程序中它是正确的。我一定是睡得太少了。我将在下面发布一个答案,以展示我真正想要实现的目标。
【解决方案2】:

这就是我想要实现的目标。关于这方面的 IBM 文档很少,没有可查找的示例。也许这对很多人来说是显而易见的,但我认为如果 IBM 在他们的文档中提供了一个类似的示例,我会为自己节省很多时间:

     #include <cmqc.h>

     #define NULL 0

     class MyClass
     {

       public:
         void use_MQCSP();

       private:
         MQCSP init_MQCSP();
         MQCSP mqcsp;
     };

     MQCSP MyClass::init_MQCSP()
     {
       MQCSP mqcsp_o = { MQCSP_DEFAULT };
       return mqcsp_o;
     }

     void MyClass::use_MQCSP()
     {
       mqcsp = init_MQCSP();
       mqcsp.AuthenticationType = MQCSP_AUTH_USER_ID_AND_PWD;
     }

     int main(int argc, char **argv)
     {

        MyClass mcl;
        mcl.use_MQCSP();

        return 0;
     }

用 gcc 编译:

g++ pcftest.cpp -o pcftest -I /opt/mqm/inc/ -L /opt/mqm/lib64/ -lmqic

使用 Sun CC 编译:

CC pcftest.cpp -o pcftest -I /opt/mqm/inc/ -L /opt/mqm/lib64/ -lmqic

【讨论】:

    【解决方案3】:

    我不确定您的 MyClass 问题与您的原始问题有何关联。而且我不是混合过程语言和面向对象语言的忠实粉丝。你为什么不选择一个然后用它来编写你的程序呢?

    这是我编写的一个 C++ MQ 程序。它将使用 MQCONNX 和 MQCSP 连接到队列管理器,然后从队列中放入消息。

    /*
     * Program Name
     *  MQTest31.cpp
     *
     * Description
     * Test program to connect to a queue manager using MQCONNX and MQCSP
     * and then put a message from a queue.
     *
     * Sample Command Line Parameters
     *   QMgrName ChlName hostname(port) QName
     *
     * Where
     *    QMgrName is the queue manager name
     *    ChlName is the name of the channel to be used
     *    hostname(port) is the hostname and port number
     *    QName is the queue name
     * i.e.
     *    MQTest31.exe MQWT1 MY.TEST.EXIT 127.0.0.1(1415) TEST.Q1
     *
     * @author Roger Lacroix, Capitalware Inc.
     */
    
     /*
      * Standard Include files
      */
    #include <iostream.h>
    #include <stdio.h>
    #include <string.h>
    
    #include <imqi.hpp>    /* MQI */
    
    /*
     * mainline
     */
    int main ( int argc, char * * argv )
    {
       /* --------------------------------------------
        * Variable declarations.
        * --------------------------------------------
        */
       ImqQueueManager  mgr;
       ImqChannel      *pchannel = 0 ;
       ImqQueue         queue;
       ImqMessage       msg;
       /* */
       char     buffer[10240];
       char     myUserId[33]   = "tester";
       char     myPassword[33] = "mypwd";
       char     testMsg[] = "This is a simple test message.";
    
       /* --------------------------------------------
        * Code section
        * --------------------------------------------
        */
       if (argc != 5)
       {
         cout << "Usage: MQTest31 QMgrName ChlName hostname(port) QName" <<endl;
         return( 1 );
       }
    
       cout << "MQTest31 Starting." <<endl;
    
       // Create object descriptor for subject queue
       mgr.setName( argv[ 1 ] );
    
       pchannel = new ImqChannel ;
       pchannel -> setHeartBeatInterval( 1 );
       pchannel -> setTransportType( MQXPT_TCP );
       pchannel -> setChannelName( argv[ 2 ] );
       pchannel -> setConnectionName( argv[ 3 ] );
    
       mgr.setChannelReference( pchannel );
    
       queue.setName( argv[ 4 ] );
    
       /*
        * Specify UserId and Password via MQCSP
        */
       mgr.setAuthenticationType(MQCSP_AUTH_USER_ID_AND_PWD);
       mgr.setUserId( myUserId );
       mgr.setPassword( myPassword );
    
       /*
        * Connect to queue manager
        */
       if ( ! mgr.connect( ) )
       {
         cout << "MQTest31: connect CC=" << mgr.completionCode()<< " : RC=" << mgr.reasonCode() <<endl;
         return( 1 );
       }
    
       /* setup queue info */
       queue.setConnectionReference( mgr );
       queue.setOpenOptions(MQOO_OUTPUT + MQOO_FAIL_IF_QUIESCING);
       queue.open( );
       cout << "MQTest31: open CC=" << queue.completionCode()<< " : RC=" << queue.reasonCode() <<endl;
    
       if ( queue.completionCode( ) == MQCC_OK )
       {
          msg.useEmptyBuffer( buffer, sizeof( buffer ) );
          msg.setMessageId( );
          msg.setCorrelationId( );
          msg.setFormat( MQFMT_STRING );      /* character string format    */
          strcpy(buffer,  testMsg);
          msg.setMessageLength( (int)strlen( testMsg ) );
    
          queue.put(msg);
          cout << "MQTest31: put CC=" << queue.completionCode()<< " : RC=" << queue.reasonCode() <<endl;
       }
    
       /* Close the queue */
       queue.close( );
       cout << "MQTest31: close CC=" << queue.completionCode()<< " : RC=" << queue.reasonCode() <<endl;
    
       /* Disconnect from the queue manager */
       mgr.disconnect( );
       cout << "MQTest31: disconnect CC=" << mgr.completionCode()<< " : RC=" << mgr.reasonCode() <<endl;
    
       /* clean up */
       if ( pchannel )
       {
          mgr.setChannelReference( );
          delete pchannel ;
       }
    
       cout << "MQTest31 Ending." <<endl;
       return( 0 );
    }
    

    【讨论】:

    • 我的问题并不是很准确,因为当时我并没有完全理解这个问题。基本上我用 c++ 编程,但 IBM 的 c++ 支持有点弱。例如,我在 c++ API 中找不到对 pcf 的支持。这就是我环绕 C API 的原因……就像我猜 xms 所做的那样。
    猜你喜欢
    • 2013-03-19
    • 2013-10-09
    • 1970-01-01
    • 2015-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多