CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 3 of 3
  1. #1
    Join Date
    Mar 2010
    Posts
    6

    A compilation/linking problem

    Please someone help with this compilation/linking problem that I am having.

    I am writing some code that uses the libpng library version 1.4.1 to work with PNG files. The library is available as source code and compiles fine using NetBeans and g++ on Debian. My code uses functions declared in the header png.h that is part of libpng. The following code results in the exact same compilation/linking error that I get for almost, if not all functions that I try to use from png.h:

    Code:
    #include <stdlib.h>
    #include <png.h>
    int main(int argc, char** argv) {
    	png_structp png_ptr = png_create_write_struct (
    		PNG_LIBPNG_VER_STRING, 0, 0, 0);
        	return (EXIT_SUCCESS);
    }
    It seems that though the linker can find the declaration, it cannot find the code for png_create_write_struct().

    Code:
    newmain.o: In function `main':
    /home/user01/NetBeansProjects/ErrTest/newmain.cc:6: undefined reference to `png_create_write_struct'
    In png.h (a very large file), png_create_write_struct is defined as:

    Code:
    extern PNG_EXPORT(png_structp,png_create_write_struct)
       PNGARG((png_const_charp user_png_ver, png_voidp error_ptr,
       png_error_ptr error_fn, png_error_ptr warn_fn)) PNG_ALLOCATED;
    And resolving the typedefs for PNG_EXPORT, PNG_ARG, and PNG_ALLOCATED yields something like:

    Code:
    extern  png_structp  png_create_write_struct (
          png_const_charp  user_png_ver, 
          png_voidp             error_ptr, 
          png_error_ptr       error_fn, 
          png_error_ptr       warn_fn));
    This declaration is found amongst those for many many other functions, but the code for these functions is not all contained in a file png.c. Instead, that code is contained in many smaller files. The code for the function png_create_write_struct() is in one called pngwrite.c.

    I've put the actual code for png_create_write_struct() at the end of this post, but, thankfully, I don't think that it is relevant to the compilation problem I am having. The code is very hard to read! Instead, it seems that locating that code is the problem.

    In trying, I thought it best to explicitly include both the png.o file (actually named libpng14_la-png.o) as well as the pngwrite.o file (actually named libpng14_la-pngwrite.o), as below. However, this results in exactly the same error -- no difference at all.

    Code:
    Running "/usr/bin/make  -f Makefile CONF=Debug" in /home/user01/NetBeansProjects/ErrTest
    
    /usr/bin/make -f nbproject/Makefile-Debug.mk SUBPROJECTS= .build-conf
    make[1]: Entering directory `/home/user01/NetBeansProjects/ErrTest'
    mkdir -p build/Debug/GNU-Linux-x86/_ext/home/user01/NetBeansProjects/ErrTest
    g++    -c -g -I/home/user01/NetBeansProjects/libpng-1.4.1 -o build/Debug/GNU-Linux-x86/_ext/home/user01/NetBeansProjects/ErrTest/newmain.o /home/user01/NetBeansProjects/ErrTest/newmain.cc
    mkdir -p dist/Debug/GNU-Linux-x86
    g++     -o /home/user01/NetBeansProjects/libpng-1.4.1/libpng14_la-pngwrite.o -o /home/user01/NetBeansProjects/libpng-1.4.1/libpng14_la-png.o -o dist/Debug/GNU-Linux-x86/errtest build/Debug/GNU-Linux-x86/_ext/home/user01/NetBeansProjects/ErrTest/newmain.o  
    build/Debug/GNU-Linux-x86/_ext/home/user01/NetBeansProjects/ErrTest/newmain.o: In function `main':
    /home/user01/NetBeansProjects/ErrTest/newmain.cc:6: undefined reference to `png_create_write_struct'
    collect2: ld returned 1 exit status
    make[1]: *** [dist/Debug/GNU-Linux-x86/errtest] Error 1
    make[1]: Leaving directory `/home/user01/NetBeansProjects/ErrTest'
    make: *** [.build-impl] Error 2
    
    Build failed. Exit value 2.
    Does anyone have any ideas as what might be the problem? Any help would be much appreciated.

    Below is the png_create_write_struct code. As far as I can tell, all of the preprocessor variables are defined except USE_FAR_KEYWORD and PNG_ERROR_NUMBERS_SUPPORTED. Oddly, because PNG_USER_MEM_SUPPORTED is defined, it seems the function is actually only the first 4-5 lines, and only calls the next function, png_create_write_struct_2()!


    Code:
    png_structp PNGAPI
    png_create_write_struct(png_const_charp user_png_ver, png_voidp error_ptr,
       png_error_ptr error_fn, png_error_ptr warn_fn)
    {
    #ifdef PNG_USER_MEM_SUPPORTED
       return (png_create_write_struct_2(user_png_ver, error_ptr, error_fn,
          warn_fn, NULL, NULL, NULL));
    }
    
    /* Alternate initialize png_ptr structure, and allocate any memory needed */
    png_structp PNGAPI
    png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
       png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
       png_malloc_ptr malloc_fn, png_free_ptr free_fn)
    {
    #endif /* PNG_USER_MEM_SUPPORTED */
       volatile int png_cleanup_needed = 0;
    #ifdef PNG_SETJMP_SUPPORTED
       volatile
    #endif
       png_structp png_ptr;
    #ifdef PNG_SETJMP_SUPPORTED
    #ifdef USE_FAR_KEYWORD
       jmp_buf jmpbuf;
    #endif
    #endif
       int i;
    
       png_debug(1, "in png_create_write_struct");
    
    #ifdef PNG_USER_MEM_SUPPORTED
       png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG,
          (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr);
    #else
       png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
    #endif /* PNG_USER_MEM_SUPPORTED */
       if (png_ptr == NULL)
          return (NULL);
    
       /* Added at libpng-1.2.6 */
    #ifdef PNG_SET_USER_LIMITS_SUPPORTED
       png_ptr->user_width_max = PNG_USER_WIDTH_MAX;
       png_ptr->user_height_max = PNG_USER_HEIGHT_MAX;
    #endif
    
    #ifdef PNG_SETJMP_SUPPORTED
    /* Applications that neglect to set up their own setjmp() and then
       encounter a png_error() will longjmp here.  Since the jmpbuf is
       then meaningless we abort instead of returning. */
    #ifdef USE_FAR_KEYWORD
       if (setjmp(jmpbuf))
    #else
       if (setjmp(png_jmpbuf(png_ptr))) /* sets longjmp to match setjmp */
    #endif
    #ifdef USE_FAR_KEYWORD
       png_memcpy(png_jmpbuf(png_ptr), jmpbuf, png_sizeof(jmp_buf));
    #endif
          PNG_ABORT();
    #endif
    
    #ifdef PNG_USER_MEM_SUPPORTED
       png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn);
    #endif /* PNG_USER_MEM_SUPPORTED */
       png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
    
       if (user_png_ver)
       {
          i = 0;
          do
          {
             if (user_png_ver[i] != png_libpng_ver[i])
                png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
          } while (png_libpng_ver[i++]);
       }
    
       if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH)
       {
         /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so
          * we must recompile any applications that use any older library version.
          * For versions after libpng 1.0, we will be compatible, so we need
          * only check the first digit.
          */
         if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] ||
             (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) ||
             (user_png_ver[0] == '0' && user_png_ver[2] < '9'))
         {
    #ifdef PNG_STDIO_SUPPORTED
            char msg[80];
            if (user_png_ver)
            {
               png_snprintf(msg, 80,
                  "Application was compiled with png.h from libpng-&#37;.20s",
                  user_png_ver);
               png_warning(png_ptr, msg);
            }
            png_snprintf(msg, 80,
               "Application  is  running with png.c from libpng-%.20s",
               png_libpng_ver);
            png_warning(png_ptr, msg);
    #endif
    #ifdef PNG_ERROR_NUMBERS_SUPPORTED
            png_ptr->flags = 0;
    #endif
            png_warning(png_ptr,
               "Incompatible libpng version in application and library");
            png_cleanup_needed = 1;
         }
       }
    
       /* Initialize zbuf - compression buffer */
       png_ptr->zbuf_size = PNG_ZBUF_SIZE;
       if (!png_cleanup_needed)
       {
          png_ptr->zbuf = (png_bytep)png_malloc_warn(png_ptr,
             png_ptr->zbuf_size);
          if (png_ptr->zbuf == NULL)
             png_cleanup_needed = 1;
       }
       if (png_cleanup_needed)
       {
           /* Clean up PNG structure and deallocate any memory. */
           png_free(png_ptr, png_ptr->zbuf);
           png_ptr->zbuf = NULL;
    #ifdef PNG_USER_MEM_SUPPORTED
           png_destroy_struct_2((png_voidp)png_ptr,
              (png_free_ptr)free_fn, (png_voidp)mem_ptr);
    #else
           png_destroy_struct((png_voidp)png_ptr);
    #endif
           return (NULL);
       }
    
       png_set_write_fn(png_ptr, NULL, NULL, NULL);
    
    #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
       png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT,
          1, NULL, NULL);
    #endif
    
       return (png_ptr);
    }
    Last edited by aardvarc; May 5th, 2010 at 10:00 AM.

  2. #2
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: A compilation/linking problem

    Are you able to build the libpng distributable? If so, it should generate libpng.a, which you can link against just by adding "-lpng" to the command line.

    Make sure that is *after* your main source file on the command line----order matters for gcc. In fact, that's probably your immediate problem.

  3. #3
    Join Date
    Mar 2010
    Posts
    6

    Re: A compilation/linking problem

    It took me a long time to put the fix in, but this was indeed the answer I needed.

    Thanks again, Lindley.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured