How to resolve the 10.1 compile errors due to esriGeometry::LONG_PTR in esriCarto.tlh

945
3
01-23-2012 09:18 AM
ScottKutz
New Contributor II
Our product uses ArcGIS Engine Runtime with the MapControl and PageLayoutControl and is written in Visual C++ (MFC), Visual Studio 2010.
References to the ArcObjects libraries are obtained via the normal mechanism of using the #import statement.

Trying to build/compile in ArcGIS 10.1 Beta 2 yields the following fatal error (repeated so many times that compile just stops):
---------------------------------
C:\ProductDevSource\StCommon\Include\StPageLayoutMapViewData.h(146): error C2872: 'LONG_PTR' : ambiguous symbol
1>          could be 'C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\basetsd.h(138) : __w64 long LONG_PTR'
1>          or       'c:\productdev\synergee\gas\unicode\debug\stnetwork\esrigeometry.tlh(719) : esriGeometry::LONG_PTR'
---------------------------------

  Investigating, it turns out that esriGeometry, starting in ArcGIS 10.1, has chosen to inlcude its own TypeDef for the LONG_PTR data type. It appears that the definition is a duplicate of what Microsoft has already defined in its own header file basetsd.h.

  However, since esriGeometry is now defining it, the compile process reports the ambiguous condition as the error shown ablve.

  We tried just including an "exclude" clause on the #import for esriGeometry to avoid using the ArcGIS definition (and let all code use the Microsoft definition) as follows:
#import "esriGeometry.olb" raw_interfaces_only raw_native_types named_guids exclude("LONG_PTR")

However, that triggered the next error from the esriCarto libary:
1>c:\productdev\synergee\gas\unicode\debug\stnetwork\esricarto.tlh(36907): error C2039: 'LONG_PTR' : is not a member of 'esriGeometry'

It turns out this error occurs because esriCarto is now explicitly referencing the esriGeometry::LONG_PTR data type in the following method definition:
virtual HRESULT __stdcall OnMessage (
        /*[in]*/ unsigned long msg,
        /*[in]*/ UINT_PTR wParam,
        /*[in]*/ esriGeometry::LONG_PTR lParam ) = 0;


  We already have many, many references to the Microsoft LONG_PTR data type throughout our code base, so it is not practical to make all of those references somehow point to the ArcGIS definition in esriGeometry::LONG_PTR.

   We are continuing to experiment with various approaches of modifying the #import statement options for esriGeometry and esriCarto, but so far have not found any way to resolve the problem. 

  We would appreciate any thoughts other developers may have on how to get past this.

  Thanks for your insights.

Scott
0 Kudos
3 Replies
RichardWatson
Frequent Contributor
Try rename:

http://msdn.microsoft.com/en-us/library/8etzzkb6(v=vs.71).aspx

I don't have 10.1 beta 2 but have had similar problems in past releases with conflicts.
0 Kudos
ScottKutz
New Contributor II
Richard,

  Yes, it seems we also end up struggling with resolving a new set of #import problems with each new major ArcGIS release.

The thing that is so frustrating on this particular item is why ArcGIS felt it needed to create its own typedef for LONG_PTR instead of just using the existing typedef provided by Microsoft in the basetsd.h header file.
- It seems that this has to cause conflicts with any existing code that is already using the Microsoft LONG_PTR typedef
- If ArcGIS really does need a custom version, then it would seem prudent for ArcGIS to choose a name different from the Microsoft name.
- We are wasting a lot of time trying to find some way to workaround this problem, when it seems ArcGIS could have avoided the problem by just using a name that is not guaranteed to conflict with the existing Microsoft typedef.

  Historically, we have been able to resolve the #import issues by using combinations of "exclude" or "rename" attributes on the #import statement. Sometimes we had to modify our source code files that interact with ArcObjects to specify new names assigned via the "rename" attribute.

  The significant thing to resolving those earlier problems was that the code that had to be adjusted was in our product source files (so we could get to it and modify it).

  The problem we have encountered now with esriGeometry::LONG_PTR is that ArcGIS itself is specifying the typedef in its esriGeometry library and then explicitly referring to that typedef in the ArcGIS esriCarto library. So we cannot get to the code that is using this new typedef to modify it.

  We have been experimenting with various combinations of the "rename" attribute on our #import statement and have been able to get close, but still no success.

When esriGeometry is imported with the following #import statement:
#import "esriGeometry.olb" raw_interfaces_only raw_native_types named_guids

the resulting series of statements in the resulting esrigeometry.tlh file are as shown below. This is what you would expect: the typedef is defined and then it is used in subsequent statements.
--------------------------------------------------
#if !defined(_WIN64)
typedef __w64 long LONG_PTR;
#else
typedef __int64 LONG_PTR;
#endif
typedef LONG_PTR esriSpatialReferenceImplHandle;
typedef LONG_PTR esriPrecisionImplHandle;
typedef LONG_PTR esriPrecisionExImplHandle;
typedef LONG_PTR esriProjectionImplHandle;
typedef LONG_PTR esriGeoTransformationImplHandle;
typedef struct _esriSegmentInfo esriSegmentInfo;
typedef LONG_PTR TopologyHandle;
typedef struct _WKSPointVA WKSPointVA;
--------------------------------------------------

  But this appaorach then also generates the fatal "ambiguous symbol" error shown in the original posting in this thread.

We tried adding the following "rename" attribute to the #import statements for esriGeometry and esriCarto:
#import "esriGeometry.olb" raw_interfaces_only raw_native_types named_guids rename("LONG_PTR", "esriLONG_PTR")
#import "esriCarto.olb"    raw_interfaces_only raw_native_types no_namespace named_guids exclude("OLE_COLOR", "OLE_HANDLE", "VARTYPE", "UINT_PTR"), rename ("ITableDefinition", "IEsriTableDefinition"), rename ("IRow", "IEsriRow")  rename("LONG_PTR", "esriLONG_PTR")

  The good news is that seemed to bypass the original problem we saw in the resulting esriCarto.tlh file by generating the following output for esriCarto:
virtual HRESULT __stdcall OnMessage (
        /*[in]*/ unsigned long msg,
        /*[in]*/ UINT_PTR wParam,
        /*[in]*/ esriGeometry::esriLONG_PTR lParam ) = 0;  <-- good: The reference into esriGeometry was adjusted to esriLONG_PTR

  However, the fatal error moved back to esriGeometry.tlh because the content of the *.tlh file generated via #import with the "rename" attribute has the effect of moving the first use of the typedef to be *before* the typedef itself is actually specified, as shown below:
--------------------------------------------------
typedef esriLONG_PTR esriSpatialReferenceImplHandle;   <-- this out-of-sequence statement position causes the problem
#if !defined(_WIN64)
typedef __w64 long esriLONG_PTR;
#else
typedef __int64 esriLONG_PTR;
#endif
typedef esriLONG_PTR esriPrecisionImplHandle;
typedef esriLONG_PTR esriPrecisionExImplHandle;
typedef esriLONG_PTR esriProjectionImplHandle;
typedef esriLONG_PTR esriGeoTransformationImplHandle;
typedef struct _esriSegmentInfo esriSegmentInfo;
typedef esriLONG_PTR TopologyHandle;
typedef struct _WKSPointVA WKSPointVA;
--------------------------------------------------

and this results in the following compile errors:

1>c:\productdev\synergee\gas\unicode\debug\stnetwork\esrigeometry.tlh(718): error C2146: syntax error : missing ';' before identifier 'esriSpatialReferenceImplHandle'
1>c:\productdev\synergee\gas\unicode\debug\stnetwork\esrigeometry.tlh(718): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\productdev\synergee\gas\unicode\debug\stnetwork\esrigeometry.tlh(718): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\productdev\synergee\gas\unicode\debug\stnetwork\esrigeometry.tlh(720): error C2371: 'esriGeometry::esriLONG_PTR' : redefinition; different basic types
1>          c:\productdev\synergee\gas\unicode\debug\stnetwork\esrigeometry.tlh(718) : see declaration of 'esriGeometry::esriLONG_PTR'
1>c:\productdev\synergee\gas\unicode\debug\stnetwork\esrigeometry.tlh(1097): error C2061: syntax error : identifier 'esriSpatialReferenceImplHandle'
1>c:\productdev\synergee\gas\unicode\debug\stnetwork\esrigeometry.tlh(2053): error C2061: syntax error : identifier 'esriSpatialReferenceImplHandle'


  So we will have to continue the investigation.

  But until this problem can be resolved, we find outselves in the position where it is not possible to physically build our product in the ArcGIS 10.1 (Beta 2) environment.

  Thanks again for your insights.

Scott
0 Kudos
ScottKutz
New Contributor II
Richard,

  We know that working through the #import statement handling is never a pretty sight.

  It appears we have identified a workaround for the problem noted in this thread, but it does take dealing with the #import process to a whole new level of ugliness.

  The previous posting identified the fact that the #import "rename" processing on the esriGeometry library ended up repositioning the first use of the renamed esriLONG_PTR typedef to the statement prior to the typedef definition, as shown below:
-------------------------------------------------------------------------------
typedef esriLONG_PTR esriSpatialReferenceImplHandle; <-- this out-of-sequence statement position causes the problem
#if !defined(_WIN64)
typedef __w64 long esriLONG_PTR;
#else
typedef __int64 esriLONG_PTR;
#endif
typedef esriLONG_PTR esriPrecisionImplHandle;
-------------------------------------------------------------------------------

  We really hate to have to do this, since it is a form of "making a bad situation worse", but we discovered that placing a duplicate of the esriGeometry typedef for the renamed esriLONG_PTR in our own header file *before* the #import "esriGeometry.olb" statement allows the esriLONG_PTR definition to be "recognized" when it encounters the out-of-sequence statement for "typedef esriLONG_PTR esriSpatialReferenceImplHandle;" (that is, it no longer results in the fatal compile error).

As a result, the 2 changes we had to make in our own header file are listed below:

1. Physically include a typedef to duplicate the ArcGIS typedef, but using the rename name ("esriLONG_PTR"), as shown below. This typedef must be located *before* any of the #import statements.
-----------------------------------
#if !defined(_WIN64)
typedef __w64 long esriLONG_PTR;
#else
typedef __int64 esriLONG_PTR;
#endif
-----------------------------------

2. Add the following rename attribute on the following two #import statements: rename("LONG_PTR", "esriLONG_PTR")
-----------------------------------
#import "esriGeometry.olb" raw_interfaces_only raw_native_types named_guids rename("LONG_PTR", "esriLONG_PTR")
#import "esriCarto.olb" raw_interfaces_only raw_native_types no_namespace named_guids exclude("OLE_COLOR", "OLE_HANDLE", "VARTYPE", "UINT_PTR"), rename ("ITableDefinition", "IEsriTableDefinition"), rename ("IRow", "IEsriRow") rename("LONG_PTR", "esriLONG_PTR")
-----------------------------------

  We are very uncomfortable with such a coding construct, but this at least lets us build and run in the environment of ArcGIS Engine Runtime 10.1 (Beta 2).

  We have submitted a Beta 2 Bug Report on this (ArcGIS10.1-000515) in an effort to make Esri aware of the problem. We are hopeful that Esri will be able to make some type of adjustment to eliminate this problem since it seems it will likely create problems for many development organizations and Business Partners.

Thanks again.

Scott
0 Kudos