× The internal search function is temporarily non-functional. The current search engine is no longer viable and we are researching alternatives.
As a stop gap measure, we are using Google's custom search engine service.
If you know of an easy to use, open source, search engine ... please contact support@midrange.com.



Sorry - I am passing the ERRC0100 error code parameter with the API
call. I didn't include it in the example - I thought it was optional (as
many are), but you're correct - it's required in this API. I used the
full ERRC0100 format of course, including the message id area and data
area.

Secondly, the first example does work. It's in production on our system,
and is heavily used. I've used this technique that I came across
somewhere to handle a variety of problems. And when I use this technique
to convert the *DTS time for a data queue message, it translates
correctly.

The first time I used it (referring specifically to the use of a pointer
based on a pointer then passed that based pointer) was when I wanted to
return all messages from a data queue into a user space. The QMHRDQM API
requires a character output field. I couldn't figure out how to point it
to the user space where I wanted the data to go.

So using this technique, I get the address of the user space, then base
a pointer variable on that address, then pass that based pointer to the
API. The result, - I get all the messages into the user space just like
I wanted. It works quite well actually.

I've always been curious as to the mechanics of how this worked, but it
did what I needed and has proved very sound used by many programmers
here to handle problems with messages in data queues (I wrote a utility
to let you add, remove, change messages in an active data queue. It's
proved very useful).

As for the second example, I haven't tried it in a single program like
you did. I'll do that next. I'm passing the data from a parent program
into a module - which is indeed prototyped. I've been working for a
while prototyping API's into easy to use modules - I have some 30
procedures/functions that I've written using similar techniques. This is
the first time I've had problems, but I've never used *DTS data as a
character argument passed between programs before.

If I can get a single level program to work but a two level program to
fail, I'll post both in their entirety.

Thanks for the help

JPW



 

 

The bitterness of poor quality remains long after low pricing is
forgotten! 

 

Cautillo, Leon M.



-----Original Message-----
From: rpg400-l-bounces@xxxxxxxxxxxx
[mailto:rpg400-l-bounces@xxxxxxxxxxxx] On Behalf Of Scott Klement
Sent: Tuesday, 28 February 2006 13:29
To: RPG programming on the AS400 / iSeries
Subject: Re: QWCCVTDT frustrations


Hi Jim,

You state that the following code works.  I find that very hard to 
believe, since the code doesn't make sense.  (I tried it, it doesn't
work 
on my system)

> InVarPtr            S                *
> (the pointer to the variable that contains the *DTS data to convert,
> passed into program)
> InVar                 S               *    Based(InVarPtr)
> OutVar              S            17A
> InFmt                S            10A   Inz('*DTS')
> OutFmt             S            10A   Inz('*YYMD')
>
> Call        'QWCCVTDT'
> Parm                                InFmt
> Parm                                InVar
> Parm                                OutFmt
> Parm                                OutVar


Why doesn't this code work?

a) The QWCCVTDT API requires at least 5 parameters, and you're only 
passing 4.

b) The API is expecting "InVar" to be a character string, and you're 
passing a pointer.  Therefore, when it reads it, it'll get the bytes of
a 
memory address rather than the bytes of an actual DTS date.

Of course, with (b) it may look like it's working, but what's really 
happening is that the API is interpreting a memory address as a DTS 
timestamp -- which of course it isn't.

Keep in mind that APIs are just programs that someone wrote.  If you
write 
a program that (for example) accepts a date field (type D) as a
parameter, 
and someone decides to call it and pass it a packed (type P) field, it 
won't work, right?  The same is true for an API.  If it expects a 
character field, you have to pass a character field.  You can't decide
to 
pass a packed field, or pointer field, or date field or anything else. 
Only a character field will work.

You may be confused because sometimes people will pass a character field

by reference instead of a pointer field by value.  However, that's not 
what you're doing... you're passing the pointer by reference instead.

Every variable is stored in a computer's memory somewhere.  So,
logically, 
there's a memory address associated with each variable. When parameters 
are passed from one place to another, it's done by "sharing" that memory

between the caller and the program that it calls.  Basically what it
does 
is pass the memory address so that the called program knows where to
look 
in memory for the parameter.  Since both programs have put their
variables 
in the same spot in memory, changes made to one affect the other. (Just 
like overlaying fields in a data structure.) This is called "passing by 
reference"

A pointer is a variable designed to hold a memory address.  Thus, if you

pass a pointer by VALUE (and it MUST be by value!) what you do is pass
the 
address stored in that pointer.  Since it's still an address being
passed, 
and you can make sure that address points to a character field, it can 
have the same effect as passing the character field by reference.

However:

a) You can only pass things by VALUE to a subprocedure, not a program.

b) In your case, you weren't passing by VALUE, so instead of passing the

address stored in the pointer, you're sharing the memory of the pointer 
itself.

In your case, when the API reads the parameter, it'll read a memory 
address and try to treat it as a DTS timestamp!


> InVar                 S            17A
> OutVar              S            17A
> InFmt                S            10A   Inz('*DTS')
> OutFmt             S            10A   Inz('*YYMD')
>
> Call        'QWCCVTDT'
> Parm                                InFmt
> Parm                                InVar
> Parm                                OutFmt
> Parm                                OutVar

This is much better.  You still have the problem that you're only
passing 
4 parameters, and the API requires at least 5. Other than that, this
code 
is correct.  And I tried it (with the 5th parm added) and it worked just

fine.

...but you say that this one doesn't work... and that confuses me.

Here's the exact code that I'm using.  This is a complete program -- you

should be able to load it without any changes, and compile and run it
and 
it should output "DSPLY  20050516132424437" (you may have to display the

job log to see the text, though)

      D InVar           s             17A   inz(x'89A37F16E9B68000')
      D OutVar          s             17A
      D InFmt           s             10A   inz('*DTS')
      D OutFmt          s             10A   inz('*YYMD')

      D ErrorCode       ds
      D    BytesProv                  10I 0 inz(0)
      D    BytesAvail                 10I 0 inz(0)

      C                   CALL      'QWCCVTDT'
      C                   parm                    InFmt
      C                   parm                    InVar
      C                   parm                    OutFmt
      C                   parm                    OutVar
      C                   parm                    ErrorCode

      c     OutVar        dsply
      c                   eval      *inlr = *on

Better yet, re-code the program to use a prototype.  The prototype will 
protect you against passing the wrong parameters to the API (that is 
assuming, of course, that the prototype is written properly).  That way,

you won't make the same mistake in the future.

Good luck


As an Amazon Associate we earn from qualifying purchases.

This thread ...


Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].

Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.