-
May 5th, 2010, 09:48 AM
#1
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-%.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.
-
May 5th, 2010, 11:13 AM
#2
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.
-
May 16th, 2010, 07:21 AM
#3
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|