Projection Callback problem

dcoggindcoggin Global Mapper UserPosts: 259Trusted User
edited April 2010 in SDK
Mike,

When using the GM_SetQueryProjectionCallback function to set a callback function for loading files with unknown projections, I am getting a #3 GM_Error_LoadError when calling either GM_LoadGenericAsciiTextLayer or GM_LoadLayerList. I only get the problem on my 32-bit builds -- the 64-bit builds work fine. I thought it was probably some memory getting overwritten but I made a stripped down test version with no dynamic memory allocation and I have the same problem. In both cases (32 and 64 bit builds) I am using the 2/22/10 build of the SDK. Any ideas?

Thanks for your help.

David

Comments

  • global_mapperglobal_mapper Administrator Posts: 17,238
    edited March 2010
    David,

    If you remove the call to GM_SetQueryProjectionCallback then does your load work ok in the 32-bit build? Can I see your callback function implementation? If you debug in does the debugger get to your callback?

    Thanks,

    Mike
    Global Mapper Support
    support@globalmapper.com
  • dcoggindcoggin Global Mapper User Posts: 259Trusted User
    edited March 2010
    Mike,

    If I remove the call to GM_SetQueryProjectionCallback then the load works fine in the 32-bit build. When I debug with the callback function the library successfully calls my callback function and GM_SelectProjection is used to set the projection. That part completes with no errors. Here is the way I am setting up the callback:

    In the Document class header file:


    extern void* g_pCallbackDoc; // global variable to get around the static member callback

    class EM_Doc
    {
    ...
    boolean
    QueryProjectionCallback
    (
    GM_Projection_t* a_Proj,
    const GM_Point_t* a_InitialPos,
    GM_ElevUnits_t8* a_ElevUnits
    );

    static boolean
    QueryProjectionCallbackSetter
    (
    GM_Projection_t* a_Proj,
    const GM_Point_t* a_InitialPos,
    GM_ElevUnits_t8* a_ElevUnits
    );
    ...
    };

    In the Document Class .cpp file:

    EM_Doc::OnNewDocument ()
    {
    ...
    GM_SetQueryProjectionCallback ((GM_QueryProjectionCallbackFunc)&EM_Doc::QueryProjectionCallbackSetter);
    ...
    }

    boolean
    EM_Doc::QueryProjectionCallback
    (
    GM_Projection_t* a_Proj,
    const GM_Point_t* a_InitialPos,
    GM_ElevUnits_t8* a_ElevUnits
    )
    {
    GM_Projection_t* pInitialProj = 0;

    ...
    // Try to guess from the hint
    if (a_InitialPos != 0)
    {
    // code to try to guess from the hint and allocate/assign pInitialProj
    }
    GM_Error_t32 theErr = GM_SelectProjection (a_Proj, pInitialProj);

    delete pInitialProj;
    pInitialProj = 0;

    if (theErr == GM_Error_OperationCanceled )
    {
    return FALSE;
    }
    else if (theErr)
    {
    ::AfxMessageBox (_T("Error selecting projection"));
    return FALSE;
    }
    }

    ...
    return TRUE;
    }

    boolean
    EM_Doc::QueryProjectionCallbackSetter
    (
    GM_Projection_t* a_Proj,
    const GM_Point_t* a_InitialPos,
    GM_ElevUnits_t8* a_ElevUnits
    )
    {
    EM_Doc* pDoc = (EM_Doc*) g_pCallbackDoc;

    return pDoc->QueryProjectionCallback (a_Proj, a_InitialPos, a_ElevUnits);
    }

    And finally in the View class .cpp file:

    void* g_pCallbackDoc;


    int EM_View::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
    if (CView::OnCreate(lpCreateStruct) == -1)
    {
    return -1; // View was not correctly created
    }
    m_pDoc = (EM_Doc*) m_pDocument;
    if (m_pDoc == NULL)
    return -1;
    ASSERT_VALID(m_pDoc);

    g_pCallbackDoc = (void*) m_pDoc;
    }

    I know this is not pretty with the way I'm calling it using a global variable, but I was doing a lot of things with class member variables in the callback function and was trying to get around the restrictions on using non-static member functions as callback functions. I have built a simplified version with the callback as a global function in a separate header and I have the same problem. The exact same code works fine in the 64-bit build.

    David
  • global_mapperglobal_mapper Administrator Posts: 17,238
    edited March 2010
    David,

    Can you first try getting the official v1.33 SDK release build from the Developers page at http://www.globalmapper.com and see if that makes a difference? It should have a build date of just a few days ago.

    If that doesn't help, can you try changing your callback to just fill in the projection with some default projection and return to see if it is something in your callback code causing the issue or just the process of calling the callback that crashes?

    Thanks,

    Mike
    Global Mapper Support
    support@globalmapper.com
  • dcoggindcoggin Global Mapper User Posts: 259Trusted User
    edited March 2010
    Mike,

    I tried the new 1.33 release with no change. I made a simple console MFC app as follows and it still doesn't work:

    #include "stdafx.h"
    #include "EM_test2.h"
    #include "GlobalMapperInterface.h"

    #ifdef _DEBUG
    #define new DEBUG_NEW
    #endif


    // The one and only application object

    CWinApp theApp;

    using namespace std;


    boolean
    QueryProjectionCallback
    (
    GM_Projection_t* a_Proj,
    const GM_Point_t* a_InitialPos,
    GM_ElevUnits_t8* a_ElevUnits
    )
    {
    ::memset (a_Proj, 0, sizeof(GM_Projection_t));
    a_Proj->mProjSys = GM_PRJ_GEO;
    a_Proj->mUnit = GM_PRJ_UNIT_ARC_DEGREES;
    a_Proj->mDatum = GM_DATUM_NAD83;
    a_Proj->mNumAttrs = 1;
    a_Proj->mAttrList->mAttr = CENTRAL_LONGITUDE;
    a_Proj->mAttrList->mValue = 0.0;

    return TRUE;
    }

    int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
    {
    int nRetCode = 0;

    // initialize MFC and print and error on failure
    if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
    {
    // TODO: change error code to suit your needs
    _tprintf(_T("Fatal Error: MFC initialization failed\n"));
    nRetCode = 1;
    }
    else
    {
    GM_SetQueryProjectionCallback ((GM_QueryProjectionCallbackFunc)&QueryProjectionCallback);

    char* czFilename = "FL_counties_ln_UTM16.shp";
    GM_LayerHandle_t32* theLayerHandleList = NULL;
    uint32 uNumLoadedLayers = 0;

    GM_Error_t32 theErr = GM_LoadLayerList (czFilename,
    &theLayerHandleList,
    &uNumLoadedLayers,
    NULL);
    if (theErr)
    {
    int x = 0;
    }
    }

    return nRetCode;
    }


    Is my call to GM_SetQueryProjectionCallback correct? If I don't register the callback function it works fine. I'll send this little VS solution to the support e-mail along with the shapefile in case it helps you look at it.

    David
  • global_mapperglobal_mapper Administrator Posts: 17,238
    edited March 2010
    David,

    Thanks for the files. I used your test project and quickly found the problem. You need to add __stdcall to your callback function declaration, as follows:

    boolean __stdcall
    QueryProjectionCallback
    (
    GM_Projection_t* a_Proj,
    const GM_Point_t* a_InitialPos,
    GM_ElevUnits_t8* a_ElevUnits
    )

    When I did that the error went away.

    Let me know if I can be of further assistance.

    Thanks,

    Mike
    Global Mapper Support
    support@globalmapper.com
  • dcoggindcoggin Global Mapper User Posts: 259Trusted User
    edited March 2010
    That did it Mike. Thanks very much for your help.

    David
  • grace12grace12 Banned Posts: 2Banned User
    edited April 2010
    Thanks very much for your help.
Sign In or Register to comment.