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



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?

As an Amazon Associate we earn from qualifying purchases.

This thread ...

Follow-Ups:
Replies:

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.