ibmi-brunch-learn

Announcement

Collapse
No announcement yet.

Wrong number of parameters for RPG function

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Wrong number of parameters for RPG function

    Hello everybody. I have a C++ program calling a function from a service program that is written in RPG. The function has the following prototype:
    Code:
    PCFTGetDmn B export
    DCFTGetDmn pi 10
    D UsId 10A const
    D BDate 7P 0 options (*nopass)
    D RB 10A options (*nopass)
    I made a prototype in C ++ as follows:
    Code:
    struct Char10 {
      char arr[10];
    };
    extern "RPG" Char10 CFTGetDmn (const char *);
    The call to this function is done like this:
    Code:
    std::string str = "ABCDEFGHIJ";
    Char10 res = CFTGetDmn (str.c_str());
    The problem is that under some conditions the CFTGetDmn function is called as if more than 1 parameter was passed to it: in the debugger you can see that %parms is greater than 1. I tried to make a case where the error would be reproduced, but I failed : everything works correctly. And only in the big program does some terrible magic happen.
    I said this error is reproducible only under certain conditions. This means that if you change the code of the function where the call to CFTGetDmn occurs, for example, change str after initialization, then the magic disappears.
    Can someone explain what is happening?

  • #2
    You have not said whether you have used the appropriate #pragma directive to tell the compiler to build operational descriptors for the call. Without them RPG will not get an accurate value for %Parms. This is all described in chapter 8 (around page 80) of the C/C++ Programmers guide.

    Comment


    • #3
      JonBoy, thanks for your help! I haven't really used #pragma descriptor. After adding this pragma, the number of parameters in the RPG function began to be determined correctly.

      Let me ask you another question about this pragma. My RPG function takes a 10-character string as the first parameter. I thought that when using this pragma, I could pass, for example, 5 characters with a null terminator. However, debugging showed that the transmitted 5 characters come to the RPG function, then a terminating zero followed by garbage. Although I expected the RPG function to get 5 characters followed by blanks.

      Doesn't the pragma do string conversions when passed from one programming language to another?

      Comment


      • #4
        To be honest I don't know - I'd be surprised if it did.

        But as a rule if you want to accept a C-style string (i.e. null terminated) in an RPG program then your C code should be passing a pointer to char and the RPG code should process the parameter via %Str( ) to get the correct string e.g. 5 characters followed by 5 blanks. Like so:
        Code:
        RPG10Char = %Str( pointerToCString );
        Basically RPG has no concept of a null terminated string as a native data type. There are sections on interlanguage ILE calls in both the C and RPG manuals that cover this stuff. My expertise in in calling C from RPG - I've never done it the other way round.

        Comment


        • #5
          From the caller's side, #pragma descriptor just describes the parameter, it doesn't change it.

          I don't think any of the languages use the operational descriptor within the called function to automatically process the passed parameter to make it fit the prototyped parameter.

          For sure RPG doesn't do anything with the parameter descriptors themselves. RPG only uses the parameter count to set %PARMS. It would be up to the RPG programmer to call the CEEDOD (Decode Operational Descriptor) API to find out exactly what kind of parameter was passed. That would also require that the RPG prototype have the OPDESC keyword to ensure that RPG callers passed the full operational descriptor.

          Comment


          • #6
            Barbara, Jon, thanks for the help!

            Resolve, perhaps, the last two questions related to the operational descriptor.

            In my case, a function written in RPG and located in a service program was called from a C ++ program. Do I need to use an operational descriptor if I call a program written in RPG from a C / C ++ program (just a separate program, * PGM object), to which I need to pass a text parameter?

            As I understand it, the operational descriptor only applies to text parameters. Why can other parameter types (packed decimal, for example) do without it?

            Comment


            • #7
              First things first, as far as I know, OpDesc are only applicable to procedure calls. Under the covers the program call mechanism is totally different. I don't know C/C++ well enough to know for sure I don't imagine that any special #pragmas would be needed.

              As to the data types - I think you are confusing what RPG itself generates in the way of OpDescs with what it needs in the way of the descriptors it receives. Barbara is far better placed to answer this than me but my understanding is that RPG requires a caller to pass minimal descriptors if it is to be able to determine the parameter count. It does not make use of descriptors for any other purpose as far as I know. In order for an RPG procedure to process descriptors passed by a caller, the procedure would need to use APIs to determine what was passed.

              RPG itself always generates minimal descriptors to allow the number of parms passed to be determined by the callee.

              Descriptors can describe other field types, but RPG itself for some reason only supports the generation of descriptors for character fields.

              Hope this helps a bit. As a rule we rarely need to worry about full descriptors. But minimal descriptors are needed to determine the actual parameter count.

              Comment


              • #8
                You don't need to use an operational descriptor if you pass the parameters from C++ in the same way the RPG procedure expects them. Even for text parameters, it would be quite difficult for an RPG procedure to use the operational descriptor to determine what type of parameter was actually passed. Normally, RPG programmers only use operational descriptors to call CEE APIs that require the descriptors. It's much much easier just to call the RPG procedure or program with the correct parameters.

                Comment


                • #9
                  For program calls (*PGM), the RPG program can always determine the number of parameters that were passed. #pragma descriptor is only needed for procedure calls and only when the procedure is checking to see how many parameters were passed.

                  Comment


                  • #10
                    Barbara, Jon, thank you for your help! It would be difficult without you.

                    Comment

                    Working...
                    X