|
Perhaps you omitted code in your C routine I don't see where you're accessing the *str input parameter. Anyway, in RPG IV if you use OPTIIONS(*STRING) and VALUE for a parm, you don't also then use %ADDR(someVar) when you pass a value to that parameter. You simply code as is. In other words: This... Pr_ChkDigit(%Addr(Wrk_Str)); Should be this... Pr_ChkDigit(Wrk_Str); And you don't need to add the NULL since OPTIONS(*STRING) does that for you. -Bob Cozzi www.RPGxTools.com If everything is under control, you are going too slow. - Mario Andretti -----Original Message----- From: c400-l-bounces+cozzi=rpgiv.com@xxxxxxxxxxxx [mailto:c400-l-bounces+cozzi=rpgiv.com@xxxxxxxxxxxx] On Behalf Of c400-l-request@xxxxxxxxxxxx Sent: Wednesday, April 20, 2005 4:38 PM To: c400-l@xxxxxxxxxxxx Subject: C400-L Digest, Vol 3, Issue 42 Send C400-L mailing list submissions to c400-l@xxxxxxxxxxxx To subscribe or unsubscribe via the World Wide Web, visit http://lists.midrange.com/mailman/listinfo/c400-l or, via email, send a message with subject or body 'help' to c400-l-request@xxxxxxxxxxxx You can reach the person managing the list at c400-l-owner@xxxxxxxxxxxx When replying, please edit your Subject line so it is more specific than "Re: Contents of C400-L digest..." Today's Topics: 1. Returning character variables from C to RPG (Krish Thirumalai) 2. RE: Returning character variables from C to RPG (Elvis Budimlic) 3. Re: Returning character variables from C to RPG (Krish Thirumalai) 4. Re: Returning character variables from C to RPG (Scott Klement) 5. Re: Returning character variables from C to RPG (Scott Klement) 6. Re: Returning character variables from C to RPG (Krish Thirumalai) ---------------------------------------------------------------------- message: 1 date: Wed, 20 Apr 2005 16:42:22 -0400 from: Krish Thirumalai <krishnithya@xxxxxxxxx> subject: [C400-L] Returning character variables from C to RPG Writing my first program in C in the ILE environment and I am really puzzled. I have the following RPG program that is calling a C function, but all i get back is a Null each time. If i put it in debug mode i can see that the value of chkdigit is correct, but then, when i get it back in my RPG, the value is NULL. Can someone point out what i am doing wrong ? RPG program D Pr_ChkDigit PR * ExtProc('Pr_ChkDigit') D * Options(*string) value D Wrk_Str s 36A D Wrk_Null s 1A Inz(X'00') D Wrk_ChkDigit s 1A D Ptr_ChkDigit s * INZ(%ADDR(Wrk_ChkDigit)) /Free Wrk_Str = '70500607050AEI02x' + Wrk_Null; Ptr_ChkDigit = Pr_ChkDigit(%Addr(Wrk_Str)); Dsply Wrk_ChkDigit; *InLr = *on; /End-Free C service program // Mod 36 Check bit calculator char* Pr_ChkDigit(char *str) { char chkdigit; char* check_bit; //Calcuations // Get checkbit from the Mapping Matrix chkdigit=reverse_map(c1,c2) ; *check_bit = chkdigit; return check_bit; } -- Krish Thirumalai ------------------------------ message: 2 date: Wed, 20 Apr 2005 15:50:39 -0500 from: "Elvis Budimlic" <ebudimlic@xxxxxxxxxxxxxxxxxxxxxxxxx> subject: RE: [C400-L] Returning character variables from C to RPG What if you use: // Mod 36 Check bit calculator char* Pr_ChkDigit(char *str) { char chkdigit; //Calcuations // Get checkbit from the Mapping Matrix chkdigit=reverse_map(c1,c2) ; *str = chkdigit; return str; } -----Original Message----- From: c400-l-bounces+ebudimlic=centerfieldtechnology.com@xxxxxxxxxxxx [mailto:c400-l-bounces+ebudimlic=centerfieldtechnology.com@xxxxxxxxxxxx] On Behalf Of Krish Thirumalai Sent: Wednesday, April 20, 2005 3:42 PM To: c400-l@xxxxxxxxxxxx Subject: [C400-L] Returning character variables from C to RPG Writing my first program in C in the ILE environment and I am really puzzled. I have the following RPG program that is calling a C function, but all i get back is a Null each time. If i put it in debug mode i can see that the value of chkdigit is correct, but then, when i get it back in my RPG, the value is NULL. Can someone point out what i am doing wrong ? RPG program D Pr_ChkDigit PR * ExtProc('Pr_ChkDigit') D * Options(*string) value D Wrk_Str s 36A D Wrk_Null s 1A Inz(X'00') D Wrk_ChkDigit s 1A D Ptr_ChkDigit s * INZ(%ADDR(Wrk_ChkDigit)) /Free Wrk_Str = '70500607050AEI02x' + Wrk_Null; Ptr_ChkDigit = Pr_ChkDigit(%Addr(Wrk_Str)); Dsply Wrk_ChkDigit; *InLr = *on; /End-Free C service program // Mod 36 Check bit calculator char* Pr_ChkDigit(char *str) { char chkdigit; char* check_bit; //Calcuations // Get checkbit from the Mapping Matrix chkdigit=reverse_map(c1,c2) ; *check_bit = chkdigit; return check_bit; } -- Krish Thirumalai _______________________________________________ This is the C programming iSeries / AS400 (C400-L) mailing list To post a message email: C400-L@xxxxxxxxxxxx To subscribe, unsubscribe, or change list options, visit: http://lists.midrange.com/mailman/listinfo/c400-l or email: C400-L-request@xxxxxxxxxxxx Before posting, please take a moment to review the archives at http://archive.midrange.com/c400-l. ------------------------------ message: 3 date: Wed, 20 Apr 2005 17:08:09 -0400 from: Krish Thirumalai <krishnithya@xxxxxxxxx> subject: Re: [C400-L] Returning character variables from C to RPG That did return the pointer back, but the original string was modified. String sent '70500607050AEI02x' String returned 'J0500607050AEI02x' I was expecting to get just the value J which is the check digit that got generated. On 4/20/05, Elvis Budimlic <ebudimlic@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote: > > What if you use: > > // Mod 36 Check bit calculator > char* Pr_ChkDigit(char *str) > { > > char chkdigit; > > //Calcuations > // Get checkbit from the Mapping Matrix > chkdigit=reverse_map(c1,c2) ; > *str = chkdigit; > return str; > > } > > -----Original Message----- > From: c400-l-bounces+ebudimlic=centerfieldtechnology.com@xxxxxxxxxxxx > [mailto:c400-l-bounces+ebudimlic=centerfieldtechnology.com@xxxxxxxxxxxx] > On > Behalf Of Krish Thirumalai > Sent: Wednesday, April 20, 2005 3:42 PM > To: c400-l@xxxxxxxxxxxx > Subject: [C400-L] Returning character variables from C to RPG > > Writing my first program in C in the ILE environment and I am really > puzzled. > > I have the following RPG program that is calling a C function, but all i > get > > back is a Null each time. If i put it in debug mode i can see that the > value > > of chkdigit is correct, but then, when i get it back in my RPG, the value > is > > NULL. > > Can someone point out what i am doing wrong ? > > RPG program > > D Pr_ChkDigit PR * ExtProc('Pr_ChkDigit') > D * Options(*string) value > > D Wrk_Str s 36A > D Wrk_Null s 1A Inz(X'00') > D Wrk_ChkDigit s 1A > D Ptr_ChkDigit s * INZ(%ADDR(Wrk_ChkDigit)) > > /Free > Wrk_Str = '70500607050AEI02x' + Wrk_Null; > Ptr_ChkDigit = Pr_ChkDigit(%Addr(Wrk_Str)); > Dsply Wrk_ChkDigit; > *InLr = *on; > /End-Free > > C service program > > // Mod 36 Check bit calculator > char* Pr_ChkDigit(char *str) > { > > char chkdigit; > char* check_bit; > > //Calcuations > // Get checkbit from the Mapping Matrix > chkdigit=reverse_map(c1,c2) ; > *check_bit = chkdigit; > return check_bit; > > } > > -- > Krish Thirumalai > _______________________________________________ > This is the C programming iSeries / AS400 (C400-L) mailing list > To post a message email: C400-L@xxxxxxxxxxxx > To subscribe, unsubscribe, or change list options, > visit: http://lists.midrange.com/mailman/listinfo/c400-l > or email: C400-L-request@xxxxxxxxxxxx > Before posting, please take a moment to review the archives > at http://archive.midrange.com/c400-l. > > _______________________________________________ > This is the C programming iSeries / AS400 (C400-L) mailing list > To post a message email: C400-L@xxxxxxxxxxxx > To subscribe, unsubscribe, or change list options, > visit: http://lists.midrange.com/mailman/listinfo/c400-l > or email: C400-L-request@xxxxxxxxxxxx > Before posting, please take a moment to review the archives > at http://archive.midrange.com/c400-l. > > -- Krish Thirumalai ------------------------------ message: 4 date: Wed, 20 Apr 2005 16:17:34 -0500 (CDT) from: Scott Klement <c400-l@xxxxxxxxxxxxxxxx> subject: Re: [C400-L] Returning character variables from C to RPG Hello, > I have the following RPG program that is calling a C function, but all i get > back is a Null each time. If i put it in debug mode i can see that the value > of chkdigit is correct, but then, when i get it back in my RPG, the value is > NULL. In your code, you declare two variables that are local to the function. A one character variable called "chkdigit" and a pointer to a character called "check_bit" > char* Pr_ChkDigit(char *str) > { > > char chkdigit; > char* check_bit; At the time that these start up, what are they set to? Nothing in particular. C doesn't initialize variables, so they could really have any value. Most of the time, they'll probably be 0x00, but you can't be sure. That also means that the pointer will be NULL, since a pointer that's set to all zeroes is NULL. Now look at the code that uses them: > //Calcuations > // Get checkbit from the Mapping Matrix > chkdigit=reverse_map(c1,c2) ; Okay, this changes the value of chkdigit. > *check_bit = chkdigit; Now, this copies the value of chkdigit to whatever memory is stored where "check_bit" points to. Where does check_bit point to? Most of the time, it'll be NULL. Sometimes it might actually point to real memory, in which case you've just corrupted that memory, because you haven't allocated anything to it! > return check_bit; And now you're returning the pointer, which will usually be NULL. It might be tempting to return &chkdigit instead. (The address of the chkdigit variable) but that would also be wrong, since this is the last statement of your function, and the memory that was allocated to the chkdigit variable will be deallocated before control is returned to the caller. IMHO, it would make more sense to return a character than to return a pointer! That way, you won't have to worry about the memory being freed up. If you DO want to work with a pointer for some reason, I strongly recommend passing that pointer in as a parameter so that it refers to the caller's storage instead of the something allocated by the function itself. That way, you don't have to worry about when it gets allocated or deallocated. Make that the caller's responsibility -- it gives the caller the option of using automatic storage or static storage or whatever they want to use. Now let's talk about your RPG program :) > D Pr_ChkDigit PR * ExtProc('Pr_ChkDigit') > D * Options(*string) value > > D Wrk_Str s 36A > D Wrk_Null s 1A Inz(X'00') > D Wrk_ChkDigit s 1A > D Ptr_ChkDigit s * INZ(%ADDR(Wrk_ChkDigit)) > > /Free > Wrk_Str = '70500607050AEI02x' + Wrk_Null; > Ptr_ChkDigit = Pr_ChkDigit(%Addr(Wrk_Str)); > Dsply Wrk_ChkDigit; > *InLr = *on; > /End-Free (Wow, is that hard to read. What happened to the spaces that put things into the right columns?) The options(*string) on the prototype says to the compiler "I want you to automatically add a x'00' to the end of the string when you pass it." Then, what's the very first thing you do in your code? You manually add a x'00'. You don't need to do that! You just told the compiler to do it for you!! In the next line of code, you call the PR_ChkDigit() function and you tell it to assign the result to your pointer called Ptr_ChkDigit. Okay, so why did you assign the address of Wrk_ChkDigit to the pointer in the D-specs, if the very first thing in your program is to change that value to something else?! Not only that, but the DSPLY that occurs on the next line won't do you any good because Wrk_ChkDigit no longer has any relationship to Ptr_ChkDigit. It doesn't make any sense! You probably intended to do the following: D Ptr_ChkDigit s * D Wrk_ChkDigit s 1A based(Ptr_ChkDigit) There's a BIG difference. When you initialize a pointer to the address of a field, RPG allocates memory for that field, and then sets the pointer to the address of the memory it allocated. When you use BASED, you say "this field is always located in the memory that I point to with the basing pointer". RPG won't allocate any memory to the field, because you can change where the field points to, so allocating memory wouldn't make sense. Basically, BASED is like dereferencing a pointer in C. In other words, these two sets of code do the same thing: D Ptr_ChkDigit s * D Wrk_ChkDigit s 1A based(Ptr_ChkDigit) Ptr_ChkDigit = %alloc(1); Wrk_ChkDigit = something; dealloc Ptr_ChkDigit; is the same as: char *ptr_chkdigit; ptr_chkdigit = malloc(1); *ptr_chkdigit = something; free(ptr_chkdigit); And the following two code snippets are likewise the same: D Ptr_ChkDigit s * inz(%addr(WrkChkDigit)) D Wrk_ChkDigit s 1A Wrk_ChkDigit = something; is the same as: char wrk_chkdigit; char *ptr_chkdigit; ptr_chkdigit = &wrk_chkdigit; wrk_chkdigit = something; Does that help? ------------------------------ message: 5 date: Wed, 20 Apr 2005 16:29:51 -0500 (CDT) from: Scott Klement <c400-l@xxxxxxxxxxxxxxxx> subject: Re: [C400-L] Returning character variables from C to RPG Hello, On Wed, 20 Apr 2005, Scott Klement wrote: > > IMHO, it would make more sense to return a character than to return a > pointer! That way, you won't have to worry about the memory being freed up. > Reading back my message, I don't think I made it very clear what I recommended. I recommend the following as the solution to your problem: D Pr_ChkDigit PR 1A ExtProc(*CWIDEN: 'Pr_ChkDigit') D str * value options(*string) D Wrk_Str s 36A D Wrk_ChkDigit s 1A /free Wrk_ChkDigit = Pr_ChkDigit('70500607050AEI02x'); dsply Wrk_ChkDigit; *inlr = *on; /end-free Or, if you prefer to put the number into a variable: /free Wrk_Str = '70500607050AEI02x'; Wrk_ChkDigit = Pr_ChkDigit(%trimr(WrkStr)); dsply Wrk_ChkDigit; *inlr = *on; /end-free And the C function should look like this: char Pr_ChkDigit(const char *str) { char chkdigit; chkdigit = reverse_map(c1,c2); return chkdigit; } Actually, there doesn't seem to be any point to using a variable for the check digit. You could just do this: char Pr_ChkDigit(const char *str) { return reverse_map(c1,c2); } Anyway, hope that helps. ------------------------------ message: 6 date: Wed, 20 Apr 2005 17:37:36 -0400 from: Krish Thirumalai <krishnithya@xxxxxxxxx> subject: Re: [C400-L] Returning character variables from C to RPG Thanks Scott, It does make more sense. I did not really want to use pointers, and i realize all the mistakes that i made. I originally had the C function just returning the character, and i had it defined as follows, but my RPG was not getting back the chkdigit that i was returning. Do i have to do something different in my C to return the character string ? char Pr_ChkDigit(char* str) { char chkdigit; //Calculations chkdigit=reverse_map(c1,c2) ; return chkdigit; } D Pr_ChkDigit PR 1A ExtProc('Pr_ChkDigit') D * value D Wrk_Str s 36A D Wrk_Null s 1A Inz(X'00') D Wrk_ChkDigit s 1A /Free Wrk_Str = '70500607050AEI02x' + Wrk_Null; Wrk_ChkDigit = Pr_ChkDigit(%Addr(Wrk_Str)); Dsply Wrk_ChkDigit; On 4/20/05, Scott Klement <c400-l@xxxxxxxxxxxxxxxx> wrote: > > Hello, > > > I have the following RPG program that is calling a C function, but all i > get > > back is a Null each time. If i put it in debug mode i can see that the > value > > of chkdigit is correct, but then, when i get it back in my RPG, the > value is > > NULL. > > In your code, you declare two variables that are local to the function. A > one character variable called "chkdigit" and a pointer to a character > called "check_bit" > > > char* Pr_ChkDigit(char *str) > > { > > > > char chkdigit; > > char* check_bit; > > At the time that these start up, what are they set to? Nothing in > particular. C doesn't initialize variables, so they could really have any > value. > > Most of the time, they'll probably be 0x00, but you can't be sure. That > also means that the pointer will be NULL, since a pointer that's set to > all zeroes is NULL. > > Now look at the code that uses them: > > > //Calcuations > > // Get checkbit from the Mapping Matrix > > chkdigit=reverse_map(c1,c2) ; > > Okay, this changes the value of chkdigit. > > > *check_bit = chkdigit; > > Now, this copies the value of chkdigit to whatever memory is stored where > "check_bit" points to. Where does check_bit point to? Most of the time, > it'll be NULL. Sometimes it might actually point to real memory, in which > case you've just corrupted that memory, because you haven't allocated > anything to it! > > > return check_bit; > > And now you're returning the pointer, which will usually be NULL. > > It might be tempting to return &chkdigit instead. (The address of the > chkdigit variable) but that would also be wrong, since this is the last > statement of your function, and the memory that was allocated to the > chkdigit variable will be deallocated before control is returned to the > caller. > > IMHO, it would make more sense to return a character than to return a > pointer! That way, you won't have to worry about the memory being freed > up. > > If you DO want to work with a pointer for some reason, I strongly > recommend passing that pointer in as a parameter so that it refers to the > caller's storage instead of the something allocated by the function > itself. That way, you don't have to worry about when it gets allocated or > deallocated. Make that the caller's responsibility -- it gives the caller > the option of using automatic storage or static storage or whatever they > want to use. > > Now let's talk about your RPG program :) > > > D Pr_ChkDigit PR * ExtProc('Pr_ChkDigit') > > D * Options(*string) value > > > > D Wrk_Str s 36A > > D Wrk_Null s 1A Inz(X'00') > > D Wrk_ChkDigit s 1A > > D Ptr_ChkDigit s * INZ(%ADDR(Wrk_ChkDigit)) > > > > /Free > > Wrk_Str = '70500607050AEI02x' + Wrk_Null; > > Ptr_ChkDigit = Pr_ChkDigit(%Addr(Wrk_Str)); > > Dsply Wrk_ChkDigit; > > *InLr = *on; > > /End-Free > > (Wow, is that hard to read. What happened to the spaces that put things > into the right columns?) > > The options(*string) on the prototype says to the compiler "I want you to > automatically add a x'00' to the end of the string when you pass it." > Then, what's the very first thing you do in your code? You manually add a > x'00'. You don't need to do that! You just told the compiler to do it for > you!! > > In the next line of code, you call the PR_ChkDigit() function and you tell > it to assign the result to your pointer called Ptr_ChkDigit. Okay, so why > did you assign the address of Wrk_ChkDigit to the pointer in the D-specs, > if the very first thing in your program is to change that value to > something else?! > > Not only that, but the DSPLY that occurs on the next line won't do you any > good because Wrk_ChkDigit no longer has any relationship to Ptr_ChkDigit. > It doesn't make any sense! > > You probably intended to do the following: > > D Ptr_ChkDigit s * > D Wrk_ChkDigit s 1A based(Ptr_ChkDigit) > > There's a BIG difference. When you initialize a pointer to the address of > a field, RPG allocates memory for that field, and then sets the pointer to > the address of the memory it allocated. > > When you use BASED, you say "this field is always located in the memory > that I point to with the basing pointer". RPG won't allocate any memory > to the field, because you can change where the field points to, so > allocating memory wouldn't make sense. > > Basically, BASED is like dereferencing a pointer in C. In other words, > these two sets of code do the same thing: > > D Ptr_ChkDigit s * > D Wrk_ChkDigit s 1A based(Ptr_ChkDigit) > > Ptr_ChkDigit = %alloc(1); > Wrk_ChkDigit = something; > dealloc Ptr_ChkDigit; > > is the same as: > > char *ptr_chkdigit; > ptr_chkdigit = malloc(1); > *ptr_chkdigit = something; > free(ptr_chkdigit); > > And the following two code snippets are likewise the same: > > D Ptr_ChkDigit s * inz(%addr(WrkChkDigit)) > D Wrk_ChkDigit s 1A > > Wrk_ChkDigit = something; > > is the same as: > > char wrk_chkdigit; > char *ptr_chkdigit; > > ptr_chkdigit = &wrk_chkdigit; > wrk_chkdigit = something; > > Does that help? > _______________________________________________ > This is the C programming iSeries / AS400 (C400-L) mailing list > To post a message email: C400-L@xxxxxxxxxxxx > To subscribe, unsubscribe, or change list options, > visit: http://lists.midrange.com/mailman/listinfo/c400-l > or email: C400-L-request@xxxxxxxxxxxx > Before posting, please take a moment to review the archives > at http://archive.midrange.com/c400-l. > > -- Krish Thirumalai ------------------------------ _______________________________________________ This is the C programming iSeries / AS400 (C400-L) digest list To post a message email: C400-L@xxxxxxxxxxxx To subscribe, unsubscribe, or change list options, visit: http://lists.midrange.com/mailman/listinfo/c400-l or email: C400-L-request@xxxxxxxxxxxx Before posting, please take a moment to review the archives at http://archive.midrange.com/c400-l. End of C400-L Digest, Vol 3, Issue 42 *************************************
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.