Menu

How to pass array of struct as out parameter

Alvin
2009-07-08
2012-11-29
  • Alvin

    Alvin - 2009-07-08

    Hello Vikram!

    I have to pass an array of struct to a DCOM server. From the DCOM's IDL, here's the method that I want to call:

    [id(43), helpstring("method ExtGetAllNodes")]    HRESULT ExtGetAllNodes([in] BYTE Group, [in] BYTE Node, [out] SAFEARRAY(udtExtParam) *ExtParamArray, [out, retval] LONG* rc);

    where the udtExtParam is a struct:

    struct udtExtParam {
        [helpstring("Parameter Code")]        SHORT    ParamCode;
        [helpstring("Parameter Value")]        VARIANT    ParamValue;
    } udtExtParam;

    I wrote a separate java class for udtExtParam like this:

    public class udtExtParam {
       
        public static JIStruct asJIStruct() {
            short paramCode = 0;
            Object paramValue = null;
           
            JIStruct jiStruct = new JIStruct();
            try {
                jiStruct.addMember(Short.valueOf(paramCode));
                jiStruct.addMember(paramValue);
            } catch (JIException jiException) {
                jiException.printStackTrace();
            }
           
            return jiStruct;
        }
    }

    I want to call the method via IJIDispatch:

    try {
        udtExtParam[] extParams = { null };
       
        Object parameters[] = { Short.valueOf(group), Short.valueOf(node),
                new JIVariant(new JIArray(extParams), true) };
        JIVariant[] variant = dispatch.callMethodA("ExtGetAllNodes", parameters);
       
        if (!variant[0].isNull()) {
            ret = variant[0].getObjectAsInt();
        }
       
    } catch (JIException e) {
        e.printStackTrace();
    }

    But I get an Internal Library Error, "the serializer deserializer was not found for class udtExtParam". Does my code make sense? If not, how will I do that? What is the correct way of invoking the ExtGetAllNodes method via idispatch and passing an array of struct as out parameter? How will I access the out parameter afterwards?

    Sorry, newbie question. Thanks in advance!

     
    • Vikram Roopchand

      Hi,
           Did you try using JIStruct directly ? Custom classes are not supported as COM needs to know how to unmarshal them (even if we can marshal them). This needs a proxy DLL in between , which we cannot provide.

      thanks,
      best regards,
      Vikram

       
      • Alvin

        Alvin - 2009-07-09

        Hi!

        What do you mean by directly? Can you give me an example using the method signature of my IDL? The other code I can think of is:

        short paramCode = 0;
        Object paramValue = null;
        JIStruct jiStruct = new JIStruct();
        jiStruct.addMember(Short.valueOf(paramCode));
        jiStruct.addMember(paramValue);

        Object parameters[] = { Short.valueOf(group), Short.valueOf(node),
            new JIVariant(new JIArray(jiStruct), true) };
        JIVariant[] variant = dispatch.callMethodA("ExtGetAllNodes", parameters);

        if (!variant[0].isNull()) {
            ret = variant[0].getObjectAsInt();
        }

        That compiles but give me an IllegalArgumentException (Only Arrays Accepted as parameter.)

        I searched your forum and the closest match that I want to achieved is similar to this post:
        https://sourceforge.net/forum/message.php?msg_id=4091705. But kstanley didn't post some example.

        By the way, if the call was successful, where will I get the returned array of struct? In the variant[1] and above? Or in the parameters[] array?
        How will I access it?

        Thank you very much. Pardon my ignorance as I'm only a new user of j-interop.

         
        • Alvin

          Alvin - 2009-07-13

          Hello Vikram!

          While waiting for your reply, I further research on your forum archive. I finally found the answer on my last question. But also through that search, and trial & error method, I found out that an array of struct is not really supported by j-interop. (Correct me if I'm wrong and give me example). I've seen samples of struct that contains array, but not array that contains struct. This is what you mean by custom classes right?

          Thanks and more power to this open source project. As a suggestion, it would be better if you will soon provide a similar com2java application of j-integra to aid developers. And you know what, I also found a Java-COM Bridge alternative that supports array of struct but in DCOM mode only. (It's obvious what is it). But personally, I don't like their generation of so many files- I can do that manually with few files using your j-interop.

           
          • Vikram Roopchand

            Hi,
                 I think the array of structs is possible now. I did some work on it last year. Try it out. The issue with your last sample was , you made a single struct and passed that as param instead of an JIStruct[] to JIArray.

            To answer another question, If the call is successful you will get the result back in JIVariant[] returned.

            Good luck,
            best regards,
            Vikram

             
            • Alvin

              Alvin - 2009-07-13

              Thanks Vikram!

              Yes, I already thought of passing a JIStruct[] array to JIArray.

              short paramCode = 0;
              Object paramValue = null;
              JIStruct jiStruct = new JIStruct();
              jiStruct.addMember(Short.valueOf(paramCode));
              jiStruct.addMember(paramValue);

              JIStruct[] structs = new JIStruct[255];
              for (int i = 0; i < structs.length; i++) {
                  structs[i] = jiStruct;
              }

              Object parameters[] = { Short.valueOf(group), Short.valueOf(node),
                  new JIVariant(new JIArray(structs), true) };
              JIVariant[] variant = dispatch.callMethodA("ExtGetAllNodes", parameters);

              if (!variant[0].isNull()) {
                  ret = variant[0].getObjectAsInt();
              }

              The code above gives me a NullPointerException:

              Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
                  at org.jinterop.dcom.core.JIMarshalUnMarshalHelper$StructImpl.getLengthInBytes(JIMarshalUnMarshalHelper.java:572)
                  at org.jinterop.dcom.core.JIMarshalUnMarshalHelper.getLengthInBytes(JIMarshalUnMarshalHelper.java:352)
                  at org.jinterop.dcom.core.JIVariant.initArrays(JIVariant.java:904)
                  at org.jinterop.dcom.core.JIVariant.<init>(JIVariant.java:803)
                  at com.checkpt.eas.device.evolve.Evolve.extGetAllNodes(Evolve.java:134)
                 
              Can you instruct me the correct way of doing this properly?

               
              • Vikram Roopchand

                Hi,
                     I think this line is incorrect "jiStruct.addMember(paramValue);" , paramValue is null. Maybe I should have a check here. But for  now, please change this to a valid value or 0 and then try again.

                best regards,
                Vikram

                 
                • Alvin

                  Alvin - 2009-07-14

                  Thanks for your patience Vikram!

                  After assigning a new Object() value to paramValue, I got this exception:

                  Internal Library Error, the serializerdeserializer was not found for class java.lang.Object.  Please check the parameters passed to JICallBuilder. [0x0000100F]
                      at org.jinterop.dcom.core.JIMarshalUnMarshalHelper.getLengthInBytes(JIMarshalUnMarshalHelper.java:350)
                      at org.jinterop.dcom.core.JIStruct.getLength(JIStruct.java:335)
                      at org.jinterop.dcom.core.JIMarshalUnMarshalHelper$StructImpl.getLengthInBytes(JIMarshalUnMarshalHelper.java:572)
                      at org.jinterop.dcom.core.JIMarshalUnMarshalHelper.getLengthInBytes(JIMarshalUnMarshalHelper.java:352)
                      at org.jinterop.dcom.core.JIArray.computeLengthArray(JIArray.java:360)
                      at org.jinterop.dcom.core.JIArray.init(JIArray.java:345)
                      at org.jinterop.dcom.core.JIArray.<init>(JIArray.java:287)
                      at com.checkpt.eas.device.evolve.Evolve.extGetAllNodes(Evolve.java:134)

                     
                  But when I changed the data type of paramValue to String, here's the exception thrown:

                  java.lang.NullPointerException
                      at org.jinterop.dcom.core.JIMarshalUnMarshalHelper$StructImpl.getLengthInBytes(JIMarshalUnMarshalHelper.java:572)
                      at org.jinterop.dcom.core.JIMarshalUnMarshalHelper.getLengthInBytes(JIMarshalUnMarshalHelper.java:352)
                      at org.jinterop.dcom.core.JIVariant.initArrays(JIVariant.java:904)
                      at org.jinterop.dcom.core.JIVariant.<init>(JIVariant.java:803)
                      at com.checkpt.eas.device.evolve.Evolve.extGetAllNodes(Evolve.java:134)

                     
                  Note that paramValue was of type VARIANT in DCOM. And both exceptions above came from filling in the Object array, not yet in the dispatch call to the method:

                  Object parameters[] = { Short.valueOf(group), Short.valueOf(node),
                      new JIVariant(new JIArray(structs, true), true) };
                     

                  I also tried using JICallBuilder, but gives me "The procedure number is out of range" exception:

                  JICallBuilder callBuilder = new JICallBuilder();
                  callBuilder.reInit();
                  callBuilder.setOpnum(43);    // ExtGetAllNodes method
                  callBuilder.addInParamAsShort(group, JIFlags.FLAG_NULL);
                  callBuilder.addInParamAsShort(node, JIFlags.FLAG_NULL);

                  short paramCode = 0;
                  String paramValue = "";
                  JIStruct struct = new JIStruct();
                  struct.addMember(Short.valueOf(paramCode));
                  struct.addMember(paramValue);

                  JIStruct[] structs = new JIStruct[255];
                  for (int i = 0; i < structs.length; i++) {
                      structs[i] = struct;
                  }
                             
                  callBuilder.addOutParamAsObject(new JIArray(structs, true), JIFlags.FLAG_NULL);
                  callBuilder.addOutParamAsType(Integer.class, JIFlags.FLAG_NULL);

                  Object[] object = dispatch.call(callBuilder);

                   
                  • Vikram Roopchand

                    Hi Alvin,
                                  Can I see your code for the first two failures ?

                    best regards,
                    Vikram

                     
                    • Alvin

                      Alvin - 2009-07-14

                      Ok, here are those. First one that throws Internal Library Error (IllegalStateException):

                      short paramCode = 0;
                      Object paramValue = new Object();
                      JIStruct jiStruct = new JIStruct();
                      jiStruct.addMember(Short.valueOf(paramCode));
                      jiStruct.addMember(paramValue);

                      JIStruct[] structs = new JIStruct[255];
                      for (int i = 0; i < structs.length; i++) {
                          structs[i] = jiStruct;
                      }

                      Object parameters[] = { Short.valueOf(group), Short.valueOf(node),
                          new JIVariant(new JIArray(structs, true), true) };
                      JIVariant[] variant = dispatch.callMethodA("ExtGetAllNodes", parameters);

                      if (!variant[0].isNull()) {
                          ret = variant[0].getObjectAsInt();
                      }

                      The second one that throws NullPointerException:

                      short paramCode = 0;
                      String paramValue = "alvin";
                      JIStruct jiStruct = new JIStruct();
                      jiStruct.addMember(Short.valueOf(paramCode));
                      jiStruct.addMember(paramValue);

                      JIStruct[] structs = new JIStruct[255];
                      for (int i = 0; i < structs.length; i++) {
                          structs[i] = jiStruct;
                      }

                      Object parameters[] = { Short.valueOf(group), Short.valueOf(node),
                          new JIVariant(new JIArray(structs, true), true) };
                      JIVariant[] variant = dispatch.callMethodA("ExtGetAllNodes", parameters);

                      if (!variant[0].isNull()) {
                          ret = variant[0].getObjectAsInt();
                      }

                       

Log in to post a comment.