From: Alan W. I. <ir...@be...> - 2017-09-14 22:48:53
|
On 2017-09-14 19:59+0100 p.d...@gm... wrote: > Hi Alan > I don't have the plplot code here right now, so can't comment on plshade(1). But i can tell you about 2d arrays. > > Statically and dynamically allocated 2d arrays are very different in memory so you cannot do > > double z[10][10]; > double **z1=(double**)z; > > Or anything else that directly casts z to be a double**. > > A static 2d array is actually a pointer to a block of memory and the compiler knows that this block of memory represents a 2d array and how to find each element in that memory – presumably one row followed by the next, then the next. > > A dynamic 2d array is actually multiple separate vectors as you described. One vector for each row of the array – they do not need to be contiguous in memory. Then there is one vector (the double **) where each element points to the beginning of each row. This is literally an vector of pointers. > > So to summarise, a double** dynamic array is a vector of pointers to each row and a double[][] static array is actually a single vector that the compiler knows to interpret as a 2d array. So it should be clear now why casting between the two cannot be done. Hi Phil: Thanks for your reply. To summarize what you have said, it appears it should be impossible to use a statically allocated z array with plshade (and presumably also for the plshades, plcont, plimage, and plvect cases). So I should probably accept that statement and move on by simply using a dynamically allocated z array with plshade in examples/c/x15c.c. However, I also hope you are willing discuss this a bit more so I have a chance to learn more from this situation and also to amplify exactly why what I am trying to do is causing a segfault. To give you some more background, my first try yesterday to use plshade with a statically allocated array used statically allocated z as the argument without any casting at all. The resulting gcc compiler warning said the following: /home/software/plplot/HEAD/plplot.git/examples/c/x15c.c:187:14: warning: passing argument 1 of ‘c_plshade’ from incompatible pointer type plshade( z, XPTS, YPTS, NULL, -1., 1., -1., 1., ^ In file included from /home/software/plplot/HEAD/plplot.git/examples/c/plcdemos.h:13:0, from /home/software/plplot/HEAD/plplot.git/examples/c/x15c.c:8: /home/software/plplot/HEAD/plplot.git/include/plplot.h:1721:1: note: expected ‘PLFLT_MATRIX’ but argument is of type ‘PLFLT (*)[46]’ c_plshade( PLFLT_MATRIX a, PLINT nx, PLINT ny, PLDEFINED_callback defined, ^ /home/software/plplot/HEAD/plplot.git/examples/c/x15c.c: In function ‘plot2’: /home/software/plplot/HEAD/plplot.git/examples/c/x15c.c:238:18: warning: passing argument 1 of ‘c_plshade’ from incompatible pointer type plshade( z, XPTS, YPTS, NULL, -1., 1., -1., 1., ^ In file included from /home/software/plplot/HEAD/plplot.git/examples/c/plcdemos.h:13:0, from /home/software/plplot/HEAD/plplot.git/examples/c/x15c.c:8: /home/software/plplot/HEAD/plplot.git/include/plplot.h:1721:1: note: expected ‘PLFLT_MATRIX’ but argument is of type ‘PLFLT (*)[46]’ c_plshade( PLFLT_MATRIX a, PLINT nx, PLINT ny, PLDEFINED_callback defined, ^ So that implies to me that the original type of PLFLT z[35][46]; is interpreted (when uncast z is an argument to plshade as in this case) as PLFLT (*z)[46] i.e., z is interpreted as a pointer to a block of stack memory consisting of 46 PLFLT's (and incrementing that pointer 35-1 times points to 35-1 different blocks of stack memory consisting of 46 PLFLT's). Have I drawn the correct conclusion here from that warning message? If so, and if you consider what is created by plAlloc2dGrid(&z, 35, 46); (which is a pointer to a heap block of memory consisting of 35 pointers to heap blocks of memory containing 46 PLFLTS), there are substantial similarities with the above interpretation of PLFLT (*z)[46] (if you take into account that in C the concepts of pointers and vectors are in many ways interchangable). Furthermore, if you accept all my above interpretations and given that the following cast (const PLFLT * const *)z completely suppresses the above compiler warning, can you be more explicit about the exact explanation of why the result segfaults at run time? I suspect the answer has to do with actual differences between pointers and vectors in C, but I would like to learn about that. There are two more related topics. I. Deprecation of plshade1? I would also appreciate your response to my idea to deprecate (and eliminate in a couple of more releases) plshade1. My justification for that proposed deprecation and eventual removal is there is currently nothing similar to that variation in API for plshades, plcont, plimage, and plvect. So my guess is that plshade1 was implemented way back when as an illustrative exercise of what a small amount of extra code would be needed for a C programmer to implement his own "1" variants of plshades, plcont, plimage, and plvect to allow him to call those kinds of API with a statically allocated z array. So assuming that plshade1 was just an illustrative exercise, I don't think we actually need that exercise as part of our regular API so my plan is to deprecate it now, and then eliminate it one or two more releases down the road, but do that elimination with #if 0 plshade1(...) { .... } #endif to keep this historical exercise without actually ever compiling it again. But if considering the above information, you still think there is no convenient way to use a statically allocated z array except through such a "1" variant of our API for plshade, AND a significant fraction of our C (and C++?) users would prefer to use that variant rather than plshade with its dynamically allocated z, maybe you would recommend we leave plshade1 in undeprecated form and also implement similar C-only "1" forms for plshades, plcont, plimage, and plvect? II. Deprecation of historical C++ API variants? One further question for you to consider is what should I do concerning all the variations on the C++ bindings API that have been unofficially deprecated for a long time now? These ~12 deprecations were only noted via comments in the bindings/c++/plstrm.h and bindings/c++/plstrm.cc with slight variations on the following comment // Deprecated version using PLINT instead of bool I assume most of our C++ users are not aware that all these "PLINT instead of bool" variants have been unofficially deprecated this way, but at the same time they are probably not using these variants much if at all now because they are not documented in the slightest or used in our examples. Therefore, I am considering officially deprecating all of these "PLINT instead of bool" variants so the user would only be able to access them using the -DPL_DEPRECATED=ON cmake option for the next release, with the idea we will completely remove these variants one or two releases after that. Is this proposed backwards incompatible change to remove cruft in the C++ binding OK with you? As you can likely tell from my recent commits, I am in a cruft-removal mood so I hope you are willing to go along with my plans I. and II. above (unless there is some strong reason you are aware of to hold back from making one or both of these changes). Alan __________________________ Alan W. Irwin Astronomical research affiliation with Department of Physics and Astronomy, University of Victoria (astrowww.phys.uvic.ca). Programming affiliations with the FreeEOS equation-of-state implementation for stellar interiors (freeeos.sf.net); the Time Ephemerides project (timeephem.sf.net); PLplot scientific plotting software package (plplot.sf.net); the libLASi project (unifont.org/lasi); the Loads of Linux Links project (loll.sf.net); and the Linux Brochure Project (lbproject.sf.net). __________________________ Linux-powered Science __________________________ |