Re: C newbie - pass a LDAP handle out to calling routine
Cool, the newer versions of PL/1 support this, too, when using the BYVALUE keyword on the ENTRY declarations: DCL CFUNC ENTRY (BIN FIXED (31) BYVALUE, BIN FLOAT (53) BYVALUE, POINTER BYVALUE) RETURNS (BIN FIXED(31)); and then: DCL X BIN FIXED (31); DCL Y BIN FLOAT (53); DCL P POINTER INIT (ADDR(STRUCT)); RC = CFUNC (X, Y, P); not sure about the syntax, just a guess. Didn't test it. Kind regards Bernd Am 08.11.2011 02:32, schrieb Frank Swarbrick: FWIW, COBOL can now call by value, if desired. given: int cfunc (int x, double x, struct t *p); do this: call 'cfunc' using value cobol-fullword cobol-double reference cobol-structure returning ret-fullword Frank -- 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
Re: C newbie - pass a LDAP handle out to calling routine
FWIW, COBOL can now call by value, if desired. given: int cfunc (int x, double x, struct t *p); do this: call 'cfunc' using value cobol-fullword cobol-double reference cobol-structure returning ret-fullword Frank From: Bernd Oppolzer bernd.oppol...@t-online.de To: IBM-MAIN@bama.ua.edu Sent: Sunday, November 6, 2011 1:10 PM Subject: Re: C newbie - pass a LDAP handle out to calling routine When calling C routines from other languages like COBOL or PL/1 (or FORTRAN), you have to take into account that in C the parameters are passed by value, whereas the other languages pass them by reference, that is, addresses of the variables. The solution is simple: to construct your C routines so that they can be called from other languages, put a star on every parameter, so that C expects pointers instead of values. Of course, when accessing the parameters inside the C functions, you have to specify the stars, too. that is: int cfunc (int *x, double *x, struct type *p, ..); Furthermore, the result type should be int, so that other languages can read the return code from the C function result. If the parameter type is pointer, you need two stars, of course (that was your point). Of course, this does not solve all the problems. You have still the issue with char strings, which are in fact vectors of single chars, so there is already a star. And you need to unterstand that when passing vectors as parameter, you normally pass the starting address. And, with languages like PL/1, you have the locator/descriptor problem. But that's another topic and has nothing to do with C. Kind regards Bernd Am 06.11.2011 20:08, schrieb Gibney, Dave: 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
Re: C newbie - pass a LDAP handle out to calling routine
On Fri, 4 Nov 2011 21:39:43 +, 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 4GL) 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:46The indirection operator cannot be applied to a pointer to an incomplete struct or union. Or WARNING CCN3068 /u/ldap/test.c:46Operation 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. -- 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
Re: C newbie - pass a LDAP handle out to calling routine
In 0de6a9840123e547b061ac5b6765c0261c1...@exmb-05.ad.wsu.edu, on 11/04/2011 at 09:39 PM, Gibney, Dave gib...@wsu.edu said: This is my first experience with C, but a language is a language after the 3rd or 4th :) To some extend, but every language has its quirks. In 0de6a9840123e547b061ac5b6765c0261c1...@exmb-05.ad.wsu.edu, on 11/04/2011 at 11:10 PM, Gibney, Dave gib...@wsu.edu said: I've found the discussion of cast in the FM, Be aware that what C calls a cast is sometimes a cast and sometimes just a type alias. Be very careful when overriding the type of a pointer. -- Shmuel (Seymour J.) Metz, SysProg and JOAT ISO position; see http://patriot.net/~shmuel/resume/brief.html We don't care. We don't have to care, we're Congress. (S877: The Shut up and Eat Your spam act of 2003) -- 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
Re: C newbie - pass a LDAP handle out to calling routine
-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 +, 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 4GL) 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:46The indirection operator cannot be applied to a pointer to an incomplete struct or union. Or WARNING CCN3068 /u/ldap/test.c:46Operation 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
Re: C newbie - pass a LDAP handle out to calling routine
When calling C routines from other languages like COBOL or PL/1 (or FORTRAN), you have to take into account that in C the parameters are passed by value, whereas the other languages pass them by reference, that is, addresses of the variables. The solution is simple: to construct your C routines so that they can be called from other languages, put a star on every parameter, so that C expects pointers instead of values. Of course, when accessing the parameters inside the C functions, you have to specify the stars, too. that is: int cfunc (int *x, double *x, struct type *p, ..); Furthermore, the result type should be int, so that other languages can read the return code from the C function result. If the parameter type is pointer, you need two stars, of course (that was your point). Of course, this does not solve all the problems. You have still the issue with char strings, which are in fact vectors of single chars, so there is already a star. And you need to unterstand that when passing vectors as parameter, you normally pass the starting address. And, with languages like PL/1, you have the locator/descriptor problem. But that's another topic and has nothing to do with C. Kind regards Bernd Am 06.11.2011 20:08, schrieb Gibney, Dave: 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
Re: C newbie - pass a LDAP handle out to calling routine
On 11/6/2011 1:10 PM, Bernd Oppolzer wrote: When calling C routines from other languages like COBOL or PL/1 (or FORTRAN), you have to take into account that in C the parameters are passed by value, whereas the other languages pass them by reference, that is, addresses of the variables. The solution is simple: to construct your C routines so that they can be called from other languages, put a star on every parameter, so that C expects pointers instead of values. Of course, when accessing the parameters inside the C functions, you have to specify the stars, too. that is: int cfunc (int *x, double *x, struct type *p, ..); Furthermore, the result type should be int, so that other languages can read the return code from the C function result. If the parameter type is pointer, you need two stars, of course (that was your point). Of course, this does not solve all the problems. You have still the issue with char strings, which are in fact vectors of single chars, so there is already a star. And you need to unterstand that when passing vectors as parameter, you normally pass the starting address. And, with languages like PL/1, you have the locator/descriptor problem. But that's another topic and has nothing to do with C. Kind regards Bernd ad We discuss all these issues, and more, in our 3 day course Cross Program Communication in z/OS. Details at: http://www.trainersfriend.com/Language_Environment_courses/m520descr.htm The course covers any mix of these languages that the students want to include: Assembler, COBOL, PL/I, and C. Lectures are set and labs available for all four languages, and you can focus on just one language or any mix you like. /ad Am 06.11.2011 20:08, schrieb Gibney, Dave: 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 -- Kind regards, -Steve Comstock The Trainer's Friend, Inc. 303-393-8716 http://www.trainersfriend.com * To get a good Return on your Investment, first make an investment! + Training your people is an excellent investment * Try our new tool for calculating your Return On Investment for training dollars at http://www.trainersfriend.com/ROI/roi.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
C newbie - pass a LDAP handle out to calling routine
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 4GL) 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:46The indirection operator cannot be applied to a pointer to an incomplete struct or union. Or WARNING CCN3068 /u/ldap/test.c:46Operation 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 -- 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
Re: C newbie - pass a LDAP handle out to calling routine
Dave, You need to cast to a pointer type that memcpy (or whatever) can handle. e.g. memcpy(foo, *((char *) ld), 10); If you want to use this a lot, it might be better to just copy to a pointer of another type: char *bar; bar = (char *) ld; memcpy(foo, *bar, 10); Also, I find it beneficial to display addresses in hex. e.g. printf(ld before bind :%08X\n,ld); In article 0de6a9840123e547b061ac5b6765c0261c1...@exmb-05.ad.wsu.edu you 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 4GL) 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:46The indirection operator cannot be applied to a pointer to an incomplete struct or union. Or WARNING CCN3068 /u/ldap/test.c:46Operation 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 -- Don Poitras - SAS Development - SAS Institute Inc. - SAS Campus Drive sas...@sas.com (919) 531-5637Cary, NC 27513 -- 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
Re: C newbie - pass a LDAP handle out to calling routine
Sorry, memcpy was a bad example. The parms to that are pointers, not dereferenced pointers. memcpy(foo, ld, 10); didn't work? I guess that's something to do with incomplete type. I'm not familiar with that. My suggestion still sort of stands though. Try: memcpy(foo, (char *) ld, 10); and for the 2nd example: memcpy(foo, bar, 10); In article 2004225459.dda808f...@panix3.panix.com you wrote: Dave, You need to cast to a pointer type that memcpy (or whatever) can handle. e.g. memcpy(foo, *((char *) ld), 10); If you want to use this a lot, it might be better to just copy to a pointer of another type: char *bar; bar = (char *) ld; memcpy(foo, *bar, 10); Also, I find it beneficial to display addresses in hex. e.g. printf(ld before bind :%08X\n,ld); In article 0de6a9840123e547b061ac5b6765c0261c1...@exmb-05.ad.wsu.edu you 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 4GL) 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:46The indirection operator cannot be applied to a pointer to an incomplete struct or union. Or WARNING CCN3068 /u/ldap/test.c:46Operation 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 -- Don Poitras - SAS Development - SAS Institute Inc. - SAS Campus Drive sas...@sas.com (919) 531-5637Cary, NC 27513 -- 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
Re: C newbie - pass a LDAP handle out to calling routine
First, thanks for the display in hex, that will help me a lot in future C (if I'm ever here again after this project) I've found the discussion of cast in the FM, it is several chapters down from where I was in a straight thru read of the Language reference. It looks like this will let me make progress. I said a language is a language and it's true, but I also know it takes a lot of practice to become fluent. I may not see C again for years once I get this thing working. I really appreciate the help the listserves can provide/ Dave Gibney Information Technology Services Washington State University -Original Message- From: IBM Mainframe Discussion List [mailto:IBM-MAIN@bama.ua.edu] On Behalf Of Don Poitras Sent: Friday, November 04, 2011 3:55 PM To: IBM-MAIN@bama.ua.edu Subject: Re: C newbie - pass a LDAP handle out to calling routine Dave, You need to cast to a pointer type that memcpy (or whatever) can handle. e.g. memcpy(foo, *((char *) ld), 10); If you want to use this a lot, it might be better to just copy to a pointer of another type: char *bar; bar = (char *) ld; memcpy(foo, *bar, 10); Also, I find it beneficial to display addresses in hex. e.g. printf(ld before bind :%08X\n,ld); In article 0DE6A9840123E547B061AC5B6765C0261C148A@EXMB- 05.ad.wsu.edu you 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 4GL) 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:46The indirection operator cannot be applied to a pointer to an incomplete struct or union. Or WARNING CCN3068 /u/ldap/test.c:46Operation 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 -- Don Poitras - SAS Development - SAS Institute Inc. - SAS Campus Drive sas...@sas.com (919) 531-5637Cary, NC 27513 -- 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
Re: C newbie - pass a LDAP handle out to calling routine
Be very, very, very careful with casting. The compiler (usually) knows more about C than a newbie coder does. If you code foo = bar and the compiler objects, there is probably a good reason. Coding foo = (FooStruct)bar may make the compiler error go away but it just trades it for a much harder to diagnose run-time error. Charles -Original Message- From: IBM Mainframe Discussion List [mailto:IBM-MAIN@bama.ua.edu] On Behalf Of Gibney, Dave Sent: Friday, November 04, 2011 4:11 PM To: IBM-MAIN@bama.ua.edu Subject: Re: C newbie - pass a LDAP handle out to calling routine First, thanks for the display in hex, that will help me a lot in future C (if I'm ever here again after this project) I've found the discussion of cast in the FM, it is several chapters down from where I was in a straight thru read of the Language reference. It looks like this will let me make progress. I said a language is a language and it's true, but I also know it takes a lot of practice to become fluent. I may not see C again for years once I get this thing working. I really appreciate the help the listserves can provide/ Dave Gibney Information Technology Services Washington State University -Original Message- From: IBM Mainframe Discussion List [mailto:IBM-MAIN@bama.ua.edu] On Behalf Of Don Poitras Sent: Friday, November 04, 2011 3:55 PM To: IBM-MAIN@bama.ua.edu Subject: Re: C newbie - pass a LDAP handle out to calling routine Dave, You need to cast to a pointer type that memcpy (or whatever) can handle. e.g. memcpy(foo, *((char *) ld), 10); If you want to use this a lot, it might be better to just copy to a pointer of another type: char *bar; bar = (char *) ld; memcpy(foo, *bar, 10); Also, I find it beneficial to display addresses in hex. e.g. printf(ld before bind :%08X\n,ld); In article 0DE6A9840123E547B061AC5B6765C0261C148A@EXMB- 05.ad.wsu.edu you 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 4GL) 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:46The indirection operator cannot be applied to a pointer to an incomplete struct or union. Or WARNING CCN3068 /u/ldap/test.c:46Operation 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 -- Don Poitras - SAS Development - SAS Institute Inc. - SAS Campus Drive sas...@sas.com (919) 531-5637Cary, NC 27513 -- 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 -- 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
Re: C newbie - pass a LDAP handle out to calling routine
To be totally correct the flag is %p. That will print a pointer in whatever notation is appropriate to the platform. Of course for z, that format is 08X. Unless it's 64-bit z. Charles -Original Message- From: IBM Mainframe Discussion List [mailto:IBM-MAIN@bama.ua.edu] On Behalf Of Gibney, Dave Sent: Friday, November 04, 2011 4:11 PM To: IBM-MAIN@bama.ua.edu Subject: Re: C newbie - pass a LDAP handle out to calling routine First, thanks for the display in hex, that will help me a lot in future C (if I'm ever here again after this project) I've found the discussion of cast in the FM, it is several chapters down from where I was in a straight thru read of the Language reference. It looks like this will let me make progress. I said a language is a language and it's true, but I also know it takes a lot of practice to become fluent. I may not see C again for years once I get this thing working. I really appreciate the help the listserves can provide/ Dave Gibney Information Technology Services Washington State University -Original Message- From: IBM Mainframe Discussion List [mailto:IBM-MAIN@bama.ua.edu] On Behalf Of Don Poitras Sent: Friday, November 04, 2011 3:55 PM To: IBM-MAIN@bama.ua.edu Subject: Re: C newbie - pass a LDAP handle out to calling routine Dave, You need to cast to a pointer type that memcpy (or whatever) can handle. e.g. memcpy(foo, *((char *) ld), 10); If you want to use this a lot, it might be better to just copy to a pointer of another type: char *bar; bar = (char *) ld; memcpy(foo, *bar, 10); Also, I find it beneficial to display addresses in hex. e.g. printf(ld before bind :%08X\n,ld); In article 0DE6A9840123E547B061AC5B6765C0261C148A@EXMB- 05.ad.wsu.edu you 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 4GL) 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:46The indirection operator cannot be applied to a pointer to an incomplete struct or union. Or WARNING CCN3068 /u/ldap/test.c:46Operation 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 -- Don Poitras - SAS Development - SAS Institute Inc. - SAS Campus Drive sas...@sas.com (919) 531-5637Cary, NC 27513 -- 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 -- 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