Integrating Go programs with C library

Recently I tried my hands at Wordnet. I loved playing around with it and then decided to make a go program from which I could invoke Wordnet, whose API was written in C.

The first step in setting up wordnet is to download it.

On my Mac OSX, I got the Unix style version. Now to build it on the machine

  1. Untar : tar -xvzf  WordNet-3.0.tar.gz
  2. cd WordNet-3.0
  3. ./configure
  4. make

On make, I got the error : ‘X11/Xlib.h’ not found.

As it turned out, I needed to install XQuartz on my machine to get that header file.

After installing XQuartz, make a softlink so that header files in XQuartz are also available to Wordnet

sudo ln -s /opt/X11/include/X11 /usr/include

The last step of Building wordnet

  1. sudo make Install

This installs everything under /usr/local/WordNet-3.0

Now to build a dynamic lib on OS X which will work with cgo.

The library is in the source under ~/WordNet-3.0/lib. The Makefile can be quickly tweaked to generate the dyn lib we need:

Locate the line with “libWN_a_CPPFLAGS = $(INCLUDES)” and replace with “libWN_a_CPPFLAGS = -fPIC -fno-common $(INCLUDES)”.

Add a new build target:

libWN.dyn: $(libWN_a_OBJECTS) $(libWN_a_DEPENDENCIES)
        -rm -f libWN.3.dylib
        gcc -dynamiclib -Wl,-headerpad_max_install_names,-undefined,dynamic_lookup,-compatibility_version,1.0,-current_version,1.0,-install_name,/usr/local/WordNet-3.0/lib/libWN.3.dylib -o libWN.3.dylib $(libWN_a_OBJECTS)

Now do

make libWN.dyn 

It should generate the needed file: libWN.3.dylib

Copy this file over to wordnet installation.

sudo cp libWN.3.dylib /usr/local/WordNet-3.0/lib  

Now lets create a go program which uses cgo. we will call one of the lib’s function,

char *findtheinfo(char *searchstr, int dbase, int ptrtyp, int whichsense)

Lets create a file called wn.go and put it in wn package

package wn
//#cgo CFLAGS: -I/usr/local/WordNet-3.0/include
//#cgo LDFLAGS: /usr/local/WordNet-3.0/lib/libWN.3.dylib
/*
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "wn.h"
static void printlicense() {
    printf("WordNet License %s\n\n%s", dblicense, license);
}
*/
import "C"
import "unsafe"
import (
        "errors"
)
func PrintLicenses() {
  C.printlicense()
}

// initialize WordNet
func InitWN() (err error)  {
  status := C.wninit()
  if int(status) != 0 { return errors.New("WN Fatal: can't open database")}
  return nil
}

// search is the item to search for, e.g. 'house'.
// dbase maps the the 'pos' or Part Of Speech, e.g. Noun, Verb, Adjective or Adverb
// ptrtyp is the search type. Example are ANTPTR, CAUSETO, et..
// whichsense should be set to 0 (ALLSENSES) to get all meanings.

func FindTheInfo(search string, dbase, ptrtyp, whichsense int) string {
  cSearch := C.CString(search)
  defer C.free(unsafe.Pointer(cSearch))

  cDbase := C.int(dbase)
  cPtrtyp := C.int(ptrtyp)
  cWhichsense := C.int(whichsense)
  result := C.findtheinfo(cSearch,cDbase, cPtrtyp, cWhichsense)
  gRes := C.GoString(result)
  return gRes
}

Ensure you have no empty lines before ‘import “C”‘ statement. It causes an error while running the program.

Now lets create a main program which calls this

main.go

package main

import (
        "fmt"
        "wn"
)

func main() {
  wn.InitWN()
  word := "root"
  fmt.Printf("Sense Results for '%s': %s\n",word, wn.FindTheInfo(word,1,5,0))
}

Now running the main program

go run main.go

Gives us the following result

Sense Results for 'root': 
8 senses of root                                                        

Sense 1
root -- ((botany) the usually underground organ that lacks buds or leaves or nodes; absorbs water and mineral salts; usually it anchors the plant to the ground)

Sense 2
beginning, origin, root, rootage, source -- (the place where something begins, where it springs into being; "the Italian beginning of the Renaissance"; "Jupiter was the origin of the radiation"; "Pittsburgh is the source of the Ohio River"; "communism's Russian root")

Sense 3
root, root word, base, stem, theme, radical -- ((linguistics) the form of a word after all affixes are removed; "thematic vowels are part of the stem")

Sense 4
root -- (a number that, when multiplied by itself some number of times, equals a given number)

Sense 5
solution, root -- (the set of values that give a true statement when substituted into an equation)

Sense 6
ancestor, ascendant, ascendent, antecedent, root -- (someone from whom you are descended (but usually more remote than a grandparent))

Sense 7
etymon, root -- (a simple form inferred as the common basis from which related words in several languages can be derived by linguistic processes)

Sense 8
root, tooth root -- (the part of a tooth that is embedded in the jaw and serves as support)

Hope you had a good time, getting Wordnet to work with go.

Later!

P.S. : Took some reference from here.

~~ Whizdumb ~~
Email : sachin.xpert@gmail.com