> -----Original Message----- > From: IBM Mainframe Discussion List [mailto:IBM-MAIN@bama.ua.edu] On > Behalf Of Bill Godfrey > Sent: Sunday, November 06, 2011 7:53 AM > To: IBM-MAIN@bama.ua.edu > Subject: Re: C newbie - pass a LDAP handle out to calling routine > > On Fri, 4 Nov 2011 21:39:43 +0000, Dave Gibney wrote: > > > This is my first experience with C, but a language is a language > after the 3rd or 4th :) > >I'm calling C for LDAP queries from Natural (Software AG "4"GL) in > batch. And it works, sort of. > >One FM is IBM Tivoli Directory Server Client Programming for z/OS > > > > If I use the sequence ldap_init, ldap_simple_bind_s, ldap_search, > ldap_unbind, it gets overloaded after 5 calls at the speed of batch. If > I leave out the unbind, it works for thousands of calls, but there is > an obvious memory leak. > > So, I want to anchor the ldap handle in the main driving program. I > made a simple C stub: > > > >extern int ret2nat (int *back_value, LDAP *ld, char *msg) > >#include <ldap.h> > > > >In ldap.h there is: > >typedef struct ldap LDAP; > > > >The examples use: > >LDAP * ld; > >To declare an ldap_handle which according to the listing is an: > >ld 6270-1:1931 Class = parameter, Length = 4 > > Type = pointer to incomplete > struct ldap > > > >I have a function: > >LDAP * bind_adlds(char *hostname, char *container, char *msg) > >And I call it: > >printf("ld before bind :%d\n",ld); /* ld before bind > :286352012 > >ld = bind_adlds(hostname, container, msg) ; > >printf("ld after bind :%d\n",ld); /* ld after bind > :283317144 > > > >but the value is not returned to the caller of ret2nat. > > > >Any attempts to use *ld in an assignment or even memcpy() get a > complier message: > >ERROR CCN3285 /u/ldap/test.c:46 The indirection operator cannot be > applied to a pointer to an incomplete struct or union. > >Or > >WARNING CCN3068 /u/ldap/test.c:46 Operation between types "int*" > and "pointer to an incomplete type" is not allowed. > > > >As I said, I am just learning how to spell C. I know I am fighting > some kind of battle of types. I welcome even derisive comments, if in > the end thay help. > > > >Dave Gibney > >Information Technology Services > >Washington State University > > > > I'm not sure I understand the design of your program. You seem to have > a "main driver" program, and an int function named "ret2nat" which > accepts an LDAP * as one of its arguments, and a "bind_adlds" function > which sets the value of an LDAP *. But I don't follow how the sequence > of function calls are supposed to work. Maybe what I have to say will > cause you to redo the design. > > What you call a "stub" might be the first statement in a function, or a > function prototype without the trailing semicolon, I'm not sure which. > I don't think the "extern" is needed for functions. > > This statement, which I presume is in your "main driver" program, > LDAP * ld; > defines a pointer to an LDAP structure, but initially it does not point > to anything. It does not put an LDAP structure in your main program. > Its value is meaningless until the ldap_init function has filled in the > pointer with the address of the LDAP structure, which is in memory > obtained by ldap_init. There is no way to tell ldap_init to use any > other memory for the LDAP structure. If you call ldap_init more than > once with the same pointer as the returned value, without calling > ldap_unbind to free the memory, ldap_init will replace the address in > that pointer with a new address of another LDAP structure, and you will > have no way to free the memory used by the first LDAP structure. (Well, > you could save a copy of the pointer first, but when would you intend > to use that copy and free the memory?) That's probably the "obvious > memory leak" you referred to. I'm not sure if you already understand > that, or if this is new information to you. > > I don't understand why your program would ever need to use *ld in an > assignment or in memcpy(). Perhaps you are mistaken in even attempting > to do that, in which case there is no point in trying to make the > assignment work. > > You mentioned "thousands of calls". If this statement: > ld = bind_adlds(hostname, container, msg) ; > is the one that will run thousands of times, I see a problem with that. > You probably don't want to change pointer ld thousands of times, > especially without intervening calls to ldap_unbind. If all of the > ldap_search calls are for the same hostname, you should assign a value > to ld one time, using ldap_init or a function of your own that uses > ldap_init, and perhaps also call ldap_simple-bind one time, and then, > for the thousands of calls, call a different function that takes ld as > an argument to perform the lap_search. Lastly, call ldap_unbind to free > the LDAP structure. > > If this is giving you a better understanding of the functions, perhaps > you will decide to reconsider your design. Or maybe I am > misunderstanding what you said.
With the assistance of several folks over on MVS-OE, I solved my problem. It is clear here that I did fail in the original question to be clear enough that my driving program is not C. The whole intent was to be able to pass that address from ldap_init back out to the non C driver so that it could be reused by the thousands of calls. The solution was: extern int ret2nat (int *back_value, LDAP **ld, char *msg) This pointer to a pointer format allows the fullword in the calling non C program hold the LDAP handle from call to call. > > ---------------------------------------------------------------------- > For IBM-MAIN subscribe / signoff / archive access instructions, > send email to lists...@bama.ua.edu with the message: GET IBM-MAIN INFO > Search the archives at http://bama.ua.edu/archives/ibm-main.html ---------------------------------------------------------------------- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@bama.ua.edu with the message: GET IBM-MAIN INFO Search the archives at http://bama.ua.edu/archives/ibm-main.html