|
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 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.