|
View:
New views
7 Messages
—
Rating Filter:
Alert me
|
|
|
cmod inherit questionhi.
Something i'm confused about (again :-). I've made this class/structure: PIKECLASS HostApiInfo { PIKEVAR int structVersion; PIKEVAR int type; PIKEVAR string name; PIKEVAR int deviceCount; PIKEVAR int defaultInputDevice; PIKEVAR int defaultOutputDevice; INIT{ } EXIT{ } } And want to use it in the next class: PIKECLASS Control { INHERIT HostApiInfo; PIKEVAR HostApiInfo Info; PIKEFUN HostApiInfo get_host_api_info(int hostApi) { const PaHostApiInfo * info; info = Pa_GetHostApiInfo(hostApi); THIS->Info->structVersion = info->structVersion; [...] RETURN(THIS->Info); } etc... But it doesn't work that way. At least the HostApiInfo class was recognised as a PIKEVAR, but when i use the structVersion function the compiler complains: error: ‘struct object’ has no member named ‘structVersion’ I know, the structure is not initialized. But where and how to do that? I tried something like THIS->Info = HostApiInfo(); But that didn't help. Probably I could get around it this time by using a mapping instead of my own struct, but i'm gonna need the real thing sooner or later anyway, and using a mapping for this is just not my idea of good programming :-) If anyone knows more about that, some hints would really help. Thanks! yvan -- Copyright only exists in the imagination of those who do not have any. |
|
|
Re: cmod inherit questionI'll take a stab at providing some places to look for answers...
I am a little conused, though... Control inherits HostApiInfo and also contains one as a member variable? You might want to take a look at the source for the Public.Xapian module. It uses inheritance, though not really any PIKEVARS, though the data is accessed very similarly, due to the next little bit of information: Though CMOD takes care of a lot of the basics for you, you're still essentially working on the C-level, so you'll need to write some C using the pike C api in order to get certain things done. As an example, in order to create an object of a particular type, you'll need to use one of the C-level functions that cause objects to be created, such as clone_object(). Also note that you'll need to push arguments for the clone, if any, onto the stack. From a practical standpoint, a PIKEVAR declaration just generates a struct member of the appropriate C-level pike datatype that gets added to the storage for the class. Then, I'm pretty sure it also causes the C-level struct to get mapped to the variable so that it's accessible at the Pike-level. I don't think that specifying the classname in the pikevar does anything useful for you; it probably just gets converted to an svalue placeholder or something similar. I find it helpful to look at the source generated by the precompiler... there are a lot of macros that are useful in working with storage, and, for example, you'll be able to see what the struct * program is called so that you can clone the HostApiInfo class, and you'll see the macro that converts an object's generic storage into that of the class you want to access... your line for THIS->info- >structVer will probably become OBJ2_HOSTAPIINFO(THIS->info)- >structVersion or something similar. Finally, I've gathered some info on C-level modules at the Pike Wiki... it's not completely organized, and there are certainly a lot of unanswered questions, but perhaps you'll find something useful. http://www.gotpike.org/PikeWiki/index.pike/PikeDevel/C%20Modules Good luck! Bill On Nov 3, 2009, at 3:48 PM, Yvan Vander Sanden wrote: > hi. > > Something i'm confused about (again :-). I've made this class/ > structure: > > PIKECLASS HostApiInfo { > PIKEVAR int structVersion; > PIKEVAR int type; > PIKEVAR string name; > PIKEVAR int deviceCount; > PIKEVAR int defaultInputDevice; > PIKEVAR int defaultOutputDevice; > > INIT{ > > } > > EXIT{ > > } > } > > And want to use it in the next class: > > PIKECLASS Control { > INHERIT HostApiInfo; > PIKEVAR HostApiInfo Info; > > PIKEFUN HostApiInfo get_host_api_info(int hostApi) { > const PaHostApiInfo * info; > info = Pa_GetHostApiInfo(hostApi); > THIS->Info->structVersion = info->structVersion; > [...] > RETURN(THIS->Info); > } > > etc... > > But it doesn't work that way. At least the HostApiInfo class was > recognised as a PIKEVAR, but when i use the structVersion function > the compiler complains: > > error: ‘struct object’ has no member named ‘structVersion’ > > I know, the structure is not initialized. But where and how to do > that? I tried something like > > THIS->Info = HostApiInfo(); > > But that didn't help. Probably I could get around it this time by > using a mapping instead of my own struct, but i'm gonna need the > real thing sooner or later anyway, and using a mapping for this is > just not my idea of good programming :-) > > If anyone knows more about that, some hints would really help. Thanks! > > yvan > > -- > Copyright only exists in the imagination of those who do not have any. |
|
|
Re: cmod inherit question2009/11/4 H. William Welliver III <hww3@...> I'll take a stab at providing some places to look for answers... Ah, yes. It is meant to be a member variable. I know that is not the way you're supposed to use inherit in c, but it works in Pike, and since my class was at least recognised since I added the inherit directive, i thought i was heading in the right direction. After a night's sleep it looks less good, i must say :-) Thanks for pointing me to the C-level code. I thought using CMOD excluded the C-level functions. I guess I'd better take a look at them too. Thanks! -- Copyright only exists in the imagination of those who do not have any. |
|
|
Re: cmod inherit questionA few things. The best way to know what CMOD does is to examine the generated .c file and find the macros generated there. The "THIS" macro is defined within each PIKECLASS block to cast the storage-pointer of the "this" object to the struct defining the member variables. That is why you can use -> references in c. However, on the c-level, all object-type PIKEVARs are defined struct *object. > And want to use it in the next class: > > PIKECLASS Control { > INHERIT HostApiInfo; > PIKEVAR HostApiInfo Info; This does work, and will be a struct *object. To access members in this object from within this class, you must use the OBJ2_HOSTAPIINFO macro, which casts an object into the struct you want. > PIKEFUN HostApiInfo get_host_api_info(int hostApi) { > const PaHostApiInfo * info; > info = Pa_GetHostApiInfo(hostApi); > THIS->Info->structVersion = info->structVersion; This should be OBJ2_HOSTAPINFO(THIS->Info)->structVersion = info->structVersion. > [...] > RETURN(THIS->Info); > } > But it doesn't work that way. At least the HostApiInfo class was > recognised as a PIKEVAR, but when i use the structVersion function the > compiler complains: > > error: ‘struct object’ has no member named ‘structVersion’ > > I know, the structure is not initialized. But where and how to do > that? I tried something like > THIS->Info = HostApiInfo(); This would be: THIS->Info = low_clone(HostApiInfo_program); call_c_initalizers(THIS->Info); But because of INHERIT pike will make a new HostApiInfo object automatically everytime a new Control object is made. The way to access it is to use the get_storage(struct object*, struct program*) function. Try something like this: #define THISOBJ Pike_fp->current_object; PIKECLASS HostApiInfo { /* ... */ } #define SUPER_HOSTAPIINFO(o) ( ((struct HostApiInfo_struct *) get_storage((o), HostApiInfo_program)) ) PIKECLASS Control { INHERIT HostApiInfo; PIKEFUN int set_version(int version) { RETURN (SUPER_HOSTAPIINFO(THISOBJ)->structVersion = version); } } (I might have missed a bracket or two and it be slightly wrong but the that's the basics) When you use reference types such as objects and strings in CMOD, you must initalize them, otherwise they will blow up in pike: PIKECLASS HostApiInfo { PIKEVAR string name; INIT{ THIS->name = NULL; } EXIT{ if (THIS->name != NULL) free_string(THIS->name); } } You should use a pike compiled with the "--with-checker" option. Otherwise you won't see your memory problems. |
|
|
Re: cmod inherit questionOn Tue, 10 Nov 2009, Johan Björklund wrote:
> A few things. The best way to know what CMOD does is to examine the generated > .c file and find the macros generated there. > > The "THIS" macro is defined within each PIKECLASS block to cast the > storage-pointer of the "this" object to the struct defining the member > variables. That is why you can use -> references in c. > > However, on the c-level, all object-type PIKEVARs are defined struct *object. [...] >> I know, the structure is not initialized. But where and how to do that? I >> tried something like >> THIS->Info = HostApiInfo(); > This would be: > > THIS->Info = low_clone(HostApiInfo_program); > call_c_initalizers(THIS->Info); A more common case would be to use clone_object() (which calls call_c_initializers() (and call_pike_initializers()) for you) instead of low_clone(). > When you use reference types such as objects and strings in CMOD, you must > initalize them, otherwise they will blow up in pike: > > PIKECLASS HostApiInfo { > PIKEVAR string name; > INIT{ > THIS->name = NULL; > } > EXIT{ > if (THIS->name != NULL) free_string(THIS->name); > } > } depending on type) and freed on exit, so both INIT and EXIT in the above example are redundant. CVARs on the other hand are NOT initialized or freed automatically (unless they've been mapped by hand), and will need INIT and EXIT code. > You should use a pike compiled with the "--with-checker" option. Otherwise > you won't see your memory problems. Not quite; --with-checker adds some code to simplify analysis by C-level code checkers (eg valgrind, purify, coverity etc). Most consistency checks are added by --with-rtldebug (runtime-level debug). -- Henrik Grubbström grubba@... Roxen Internet Software AB |
|
|
Re: cmod inherit questionHenrik Grubbström wrote:
> > Not quite; --with-checker adds some code to simplify analysis by > C-level code checkers (eg valgrind, purify, coverity etc). Most > consistency checks are added by --with-rtldebug (runtime-level debug). > I think "--with-cleanup-on-exit" is the one I was really thinking of. It gives a list of the leaked objects with line numbers? --with-cleanup-on-exit Do full cleanup at exit to detect leaks better. --with-dmalloc Enable memory leak checks. --with-dmalloc-malloc Enable overloading of malloc(3) --with-dmalloc-malloc-leaks Report memory allocated by malloc(3) as leaks. --with-dmalloc-trace enable tracepoints --with-dmalloc-c-stack-trace record C stack traces for block allocations --with-dmalloc-track-free track freed memory too --with-debug same as --with-cdebug --with-rtldebug --without-debug same as --without-cdebug --without-rtldebug --with-rtldebug enable run time self tests It might it be worth it to try all of these when writing a cmod. |
|
|
Re: cmod inherit questionJohan Björklund <johbjo09@...> skrev:
> I think "--with-cleanup-on-exit" is the one I was really thinking of. > It gives a list of the leaked objects with line numbers? You get line numbers where the block has been only if you combine it with --with-dmalloc, but note that it also makes pike a lot slower and memory consuming. If you also add --with-dmalloc-c-stack-trace, you'll get backtraces of the C stack where the leaked blocks were allocated, provided you're using GNU libc. |
| Free embeddable forum powered by Nabble | Forum Help |