cwindowsgocgo

CGO undefined reference to `TIFFGetField'


I am mostly working on Go projects atm, but I have to use CGO for part of my project on the purpose of editing TIF files from Go with C, because of parameter pass-through. I am not familiar with C, but it seems the only way to solve our problem.

The problem is when I theoretically set up the Go part, and wanted to use my C code, it drops undefined reference to xxxx'` with TIFFGetField,_TIFFmalloc,TIFFReadRGBAImage function calls.

Probably I am not even importing the libtiff libary in the right way. The funny thing is the first code of the C code itself is TIFF* tif = TIFFOpen("foo.tif", "w"); does not have reference error to TIFFOpen, only the others (TIFFGetField,_TIFFmalloc,TIFFReadRGBAImage,_TIFFfree,TIFFClose)

my go code is

package main

// #cgo CFLAGS: -Ilibs/libtiff/libtiff
// #include "tiffeditor.h"
import "C"

func main() {
    C.tiffEdit()
}
#include "tiffeditor.h"
#include "tiffio.h"

void tiffEdit(){
    TIFF* tif = TIFFOpen("foo.tif", "w");
    if (tif) {
        uint32 w, h;
        size_t npixels;
        uint32* raster;

        TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
        TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
        npixels = w * h;
        raster = (uint32*) _TIFFmalloc(npixels * sizeof (uint32));
        if (raster != NULL) {
            if (TIFFReadRGBAImage(tif, w, h, raster, 0)) {
            //
            }
            _TIFFfree(raster);
        }
        TIFFClose(tif);
    }
}

My goal on first is just to establish libtiff with my go code and make it to recognise the functions libtiff, so I can focus on solving the problem itself.


Solution

  • If you see the message "undefined reference to xxx" in cgo. It is very likely that you're missing the linking to the shared library.

    I'm not quite familiar to this package, but i suggest you could try add something as below to make your program link to the C dynamic library:

    // #cgo LDFLAGS: -lyour-lib
    

    In case above, i link my go program to a C dynamic library called "libyour-lib.so".

    Example

    Assumed that your TIFF source comes from http://www.simplesystems.org/libtiff/

    Steps

    1. Download the source codes
    2. Check README.md (or INSTALL) to read the guide about how to compile this C library
    3. Follows provided instructions and install the C library
    4. If you're doing correctly without modifying default settings, you should find tiff headers in /usr/local/include and its dynamic libraries in /usr/local/lib
    5. Integrates these stuffs to your go program by having proper hints for cgo compiler.

    Codes

    I've build this program successfully, and executed as expected. It might be a good starting point for you.

    package main
    
    // #cgo LDFLAGS: -ltiff
    // #include "tiffio.h"
    // #include <stdlib.h>
    import "C"
    
    import (
        "fmt"
        "unsafe"
    )
    
    func main() {
        path, perm := "foo.tif", "w"
    
        // Convert Go string to C char array. It will do malloc in C,
        // You must free these string if it no longer in use.
        cpath := C.CString(path)
        cperm := C.CString(perm)
    
        // Defer free the memory allocated by C.
        defer func() {
            C.free(unsafe.Pointer(cpath))
            C.free(unsafe.Pointer(cperm))
        }()
    
        tif := C.TIFFOpen(cpath, cperm)
        if tif == nil {
            panic(fmt.Errorf("cannot open %s", path))
        }
    
        C.TIFFClose(tif)
    }