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