[Proj] PROJ 4.8.0, projects.h and projPJ struct

Eric Miller EMiller at dfg.ca.gov
Wed Apr 11 17:50:05 EST 2012


José,

I don't have a strong opinion about the matter, but I will reiterate
what has already been written.

The "projects.h" file has been noted as internal/private for many
years.  I don't know when the "private" designation first appeared, but
it was at least five years ago.  The "proj_api.h" header was created to
provide the public api for consumers of the library. Again, this was
many years ago.

I might have waited for a 5.0 release to break the old API by removing
"projects.h", but not everybody follows or agrees with the major/minor
API compatibility concept.

As to why the structure should be hidden, I can only say that it is
pretty standard practice to hide the implementation details from the
outside world.  Usually, that insulates the outside world from changes
that would otherwise break their code.  For instance, if a particular
variable was renamed or removed from PJConsts, your application might
break.  Should the library internals be held captive to the outside
world for backwards compatibility? For how long?

See: http://en.wikipedia.org/wiki/Information_hiding

>>> On 4/11/2012 at  1:50 PM, José Luis García Pallero
<jgpallero at gmail.com> wrote:
> 
> Hello:
> 
> This function sounds good, but I have a couple of objections:
> 
> 1. First of all, the portability of old code. The programs that
until
> now include projects.h instead proj_api.h should be corrected. I
> propose to rename projects.h to projects_internal.h (for example)
and
> create a new projects.h that contains only #include<proj_api.h>
Then,
> it can be maintained in programs the #include<projects.h> and it
runs
> always: prior to 4.8.0 and 4.8.0 or higher. Previously on this same
> topic I explained that is impossible to check automatically the
> version of PROJ via PJ_VERSION and select the correct header to
> include because if projects.h is included after proj_api.h some
errors
> of conflicting types appears. Creating new projects.h could avoid
this
> gotcha.
> 
> 2. What about the old code that uses explicitly some fields of
projPJ
> structs? Why in 4.8.0 projPJ fields are not public? For old code
that
> uses explicitly fields of projPJ the solution of the point 1 is not
> valid. Another solution could be to define explicitly the PJ struct
in
> proj_api.h. Whith this solution plus the new projects.h I think that
> almost all old code should have not problems with new 4.8.0 version
> 
> Cheers
> 
> El día 11 de abril de 2012 19:27, Frank Warmerdam
> <warmerdam at pobox.com> escribió:
>> Eric,
>>
>> This seems reasonable.  Don't hesitate to file a ticket ideally with
a 
> patch.
>>
>> Best regards,
>> Frank
>>
>> On Wed, Apr 11, 2012 at 8:25 AM, Eric Miller <EMiller at dfg.ca.gov>
wrote:
>>> I think that being able to interrogate the projection definition to
know
>>> if it has an inverse is useful, so a function should be added to
>>> proj_api.h.
>>>
>>> Perhaps:
>>>
>>> int pj_has_inverse(projPJ);
>>>
>>> And in pj_utils.c
>>>
>>>
/******************************************************************/
>>> /*                                 pj_has_inverse()
>>>            */
>>> /*
>>>                   */
>>> /*            Return TRUE if this coordinate system object has    
*/
>>> /*            and inverse projection method.
>>>  */
>>>
/*****************************************************************/
>>> int pj_has_inverse( PJ *pj )
>>> {
>>>         return pj != NULL && pj->inv != NULL;
>>> }
>>>
>>> --
>>>
>>> Eric G. Miller
>>> Software Developer
>>> CA Dept. of Fish & Game
>>>
>>>
>>>>>> On 4/11/2012 at  3:30 AM, José Luis García Pallero
>>> <jgpallero at gmail.com>
>>> wrote:
>>>> Hello:
>>>>
>>>> As it is said in NEWS files from PROJ 4.8.0 now proj_api.h file
>>> should
>>>> be included in programs instead projects.h. I've tried to compile
my
>>>> old code (that has no problems with 4.7.0) and I've obtained a
>>> warning
>>>> and an error.
>>>> In my code I have a declaration like
>>>>
>>>> projPJ proyec;
>>>>
>>>> and I use them later as
>>>>
>>>> proyec = pj_init_plus(param);
>>>>
>>>> and more later, in order to check if a projections has inverse
step:
>>>>
>>>> if(proyec->inv==0)
>>>> {
>>>> ......
>>>> }
>>>>
>>>> If I compile the program using 4.8.0 version I obtain a warning
and
>>> an
>>>> error:
>>>>
>>>> geocproj.c:202:14: warning: dereferencing *void ** pointer
>>> [enabled by
>>>> default]
>>>> geocproj.c:202:14: error: request for member *inv* in something
>>> not a
>>>> structure or union
>>>>
>>>> Looking proj_api.h file, in both versions 4.7.0 and 4.8.0 I can
see
>>> the
>>>> block
>>>>
>>>> for 4.7.0
>>>>
>>>> #if !defined(PROJECTS_H)
>>>>     typedef struct { double u, v; } projUV;
>>>>     typedef void *projPJ;
>>>>     #define projXY projUV
>>>>     #define projLP projUV
>>>> #else
>>>>     typedef PJ *projPJ;
>>>> #   define projXY     XY
>>>> #   define projLP       LP
>>>> #endif
>>>>
>>>> for 4.8.0
>>>>
>>>> #if !defined(PROJECTS_H)
>>>>     typedef struct { double u, v; } projUV;
>>>>     typedef void *projPJ;
>>>>     #define projXY projUV
>>>>     #define projLP projUV
>>>>     typedef void *projCtx;
>>>> #else
>>>>     typedef PJ *projPJ;
>>>>     typedef projCtx_t *projCtx;
>>>> #   define projXY     XY
>>>> #   define projLP       LP
>>>> #endif
>>>>
>>>> Both are the same (except for the ctx context). In both if
>>> PROJECTS_H
>>>> is not defined (i.e. if projects.h was not included) the type
projPJ
>>>> is defined as void* instead PJ*. PJ is defined in projects.h. But
in
>>>> the include/ folder of 4.8.0 project.h was not copied, so it's
>>>> impossible to use it. So I can't use the 'inv' field and I
suppone
>>> no
>>>> PJ struct at all as projPJ was defined as void*. Then which is
the
>>>> correct way in order to use the new PROJ 4.8.0 version?
>>>>
>>>>
>>>>
>>>> On the other hand, suppose that 4.8.0 works well in my case only
>>>> including proj_api.h. Then my problem is that if I have not
>>> knowledge
>>>> about the version of PROJ in one computer, how can I proceed in
>>> order
>>>> to use the correct include depending versions.
>>>> First of all, can I use version 4.7.0 (for example) with only
>>>> #include<proj_api.h>? In my case the answer is NO because I
obtain
>>> the
>>>> same warning and error that in 4.8.0. Then I try:
>>>>
>>>> #include<proj_api.h>
>>>> #if PJ_VERSION<480
>>>> #include<projects.h>
>>>> #endif
>>>>
>>>> PJ_VERSION is defined in proj_api.h. I check if version is older
>>> than
>>>> 4.8.0 and try to include then projects.h. But I obtain some
errors:
>>>>
>>>> /usr/include/projects.h:139:33: error: conflicting types for
>>> *projUV*
>>>> /usr/include/proj_api.h:54:37: note: previous declaration of
>>> *projUV*
>>>> was here
>>>> geocproj.c: In function *ProjFwd*:
>>>> geocproj.c:120:9: error: incompatible type for argument 1 of
>>> *pj_fwd*
>>>> /usr/include/proj_api.h:66:8: note: expected *projUV* but
>>> argument is
>>>> of type *projUV*
>>>> geocproj.c: In function *ProjInv*:
>>>> geocproj.c:202:14: warning: dereferencing *void ** pointer
>>> [enabled by
>>>> default]
>>>> geocproj.c:202:14: error: request for member *inv* in something
>>> not a
>>>> structure or union
>>>> geocproj.c:223:9: error: incompatible type for argument 1 of
>>> *pj_inv*
>>>> /usr/include/proj_api.h:67:8: note: expected *projUV* but
>>> argument is
>>>> of type *projUV*
>>>>
>>>> We can see conflicting type errors due to definitions of projUV
in
>>>> proj_api.h and projects.h.
>>>>
>>>> Opinions about?
>>>>
>>>> Cheers




More information about the Proj mailing list