Sunday, October 2, 2022
HomeGolangUtilizing C Dynamic Libraries In Go Applications

Utilizing C Dynamic Libraries In Go Applications


My son and I have been having enjoyable final weekend constructing a console based mostly recreation in Go. I used to be recreating a recreation from my youth, again after I was programming on a Kaypro II.

I liked this laptop. I’d write video games in BASIC on all of it day and night time. Did I point out it was moveable. The keyboard would strap in and you possibly can carry it round. LOL.

However I digress, again to my Go program. I found out a means to make use of the VT100 escape character codes to attract out a easy display screen and began programming a number of the logic.

Then one thing horrible occurred and I had a serious flashback. I couldn’t get enter from stdin with out hitting the enter key. Ahhhhh  I spent all weekend studying up on how you can make this occur. I even discovered two Go libraries that had assist for this however they didn’t work. I noticed that if I used to be going to make this occur I wanted to construct the performance in C and hyperlink that to my Go program.

After a 4 hour coding session on the native Irish pub, I figured it out. I want to thank Guinness for the inspiration and encouragement I wanted. Perceive that for the previous 10 years I’ve been writing home windows companies in C#. For 10 years earlier than that I used to be writing C/C++ however on the Microsoft stack. Every little thing I used to be studying: gcc, gco, static and shared libraries on the Mac and Linux, and many others, was overseas to me. I had rather a lot to be taught and nonetheless do.

In spite of everything my analysis it grew to become clear I wanted to make use of the ncurses dynamic library. I made a decision to write down a easy program in C utilizing the library. If I may make it work in a compiled C program, I used to be positive I may get it to work in Go.

Screen Shot

The ncurses library on the Mac is positioned in /usr/lib. Here’s a hyperlink to the documentation:

https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/ncurses.3x.html

Right here is the C header file code for the take a look at program:

take a look at.h

int GetCharacter();
void InitKeyboard();
void CloseKeyboard();

And now the code for the C supply file:

take a look at.c

#embrace
#embrace <stdio.h>
#embrace “take a look at.h”

int foremost() {
    InitKeyboard();

    printf(“nEnter: “);
    refresh();

    for (;;) {
        int r = GetCharacter();
        printf(“%c”, r);
        refresh();

        if (r == ‘q’) {
            break;
        }
    }

    CloseKeyboard();

    return 0;
}

void InitKeyboard() {
    initscr();
    noecho();
    cbreak();
    keypad(stdscr, TRUE);
    refresh();
}

int GetCharacter() {
    return getch();
}

void CloseKeyboard() {
    endwin();
}

Now the laborious half. How do I construct this program utilizing the gcc compiler? I need to be sure that I’m utilizing the identical compiler that Go is utilizing. I additionally need to be sure that I’m utilizing the naked minimal parameters and flags.

After about an hour of researching, I got here up with this makefile. I advised you, I’ve by no means accomplished this earlier than.

makefile

construct:
    rm -f take a look at
    gcc -c take a look at.c
    gcc -lncurses -r/usr/lib -o take a look at take a look at.o
    rm -f *.o

Once you run the make command it should search for a file referred to as makefile within the native listing and execute it. Remember that every command is one (1) TAB to the suitable. In the event you use areas you’ll have issues. Clearly you’ll be able to run these command manually as properly. I constructed this makefile for comfort.

Let’s break down the gcc compiler calls from the makefile:

This name to gcc is creating an object file referred to as take a look at.o from the supply file take a look at.c. The -c parameter tells gcc to simply compile the supply file and create an object file referred to as take a look at.o

gcc -c take a look at.c

This second name to gcc hyperlinks the take a look at.o object file along with the shared dynamic library libncurses.dylib to create the take a look at executable file. The -l (minus lowercase L) parameter is telling gcc to hyperlink the libncurses.dylib file and the -r (minus lowercase R) parameter is telling gcc the place it could discover the library. The -o (minus lowercase O) parameter tells gcc to create an executable output file referred to as take a look at and at last we inform gcc to incorporate take a look at.o within the hyperlink operation.

gcc -lncurses -r/usr/lib -o take a look at take a look at.o

As soon as these two gcc instructions run we now have a working model of this system referred to as take a look at. You could run this program from a terminal window for it to work. To execute this system sort ./take a look at from the terminal window:

Screen Shot

Right here I began typing letters that are being displayed by the decision to printf contained in the for loop.

As quickly as I hit the letter ‘q’, this system terminates.

I now have a working model of a program that makes use of the ncurses dynamic library I need to use in my Go program. Now I have to discover a technique to wrap these calls right into a dynamic library that I can hyperlink to from Go.

I used to be very lucky to seek out these internet pages which brilliantly present every thing we have to know to create shared and dynamic libraries:

http://www.adp-gmbh.ch/cpp/gcc/create_lib.html

http://stackoverflow.com/questions/3532589/how-to-build-a-dylib-from-several-o-in-mac-os-x-using-gcc

Let’s work collectively on making all this work in Go. Begin with establishing a Workspace for our new venture:

Screen Shot

I’ve created a folder referred to as Keyboard and two sub-folders referred to as DyLib and TestApp.

Contained in the DyLib folder we now have our C based mostly dynamic library code with a makefile. Contained in the TestApp folder we now have a single go supply code file to check our Go integration with the brand new dynamic library.

Right here is the C header file for the dynamic library. It’s similar to the C header file I used within the take a look at software.

keyboard.h

int GetCharacter();
void InitKeyboard();
void CloseKeyboard();

Right here is the C supply file that implements these capabilities. Once more it’s similar to the C supply file from the take a look at software with out the primary perform. We’re constructing a library so we don’t need foremost.

keyboard.c

#embrace
#embrace “keyboard.h”

void InitKeyboard() {
    initscr();
    noecho();
    cbreak();
    keypad(stdscr, TRUE);
    refresh();
}

int GetCharacter() {
    return getch();
}

void CloseKeyboard() {
    endwin();
}

Right here is the makefile for creating the dynamic library:

makefile

dynamic:
    rm -f libkeyboard.dylib
    rm -f ../TestApp/libkeyboard.dylib
    gcc -c -fPIC keyboard.c
    gcc -dynamiclib -lncurses -r/usr/lib -o libkeyboard.dylib keyboard.o
    rm -f keyboard.o
    cp libkeyboard.dylib ../TestApp/libkeyboard.dylib

shared:
    rm -f libkeyboard.so
    rm -f ../TestApp/libkeyboard.so
    gcc -c -fPIC keyboard.c
    gcc -shared -W1 -lncurses -r/usr/lib -soname,libkeyboard.so -o libkeyboard.so keyboard.o
    rm -f keyboard.o
    cp libkeyboard.so ../TestApp/libkeyboard.so

With this make file you’ll be able to construct both a dynamic library or shared library. In the event you simply run the make command with none parameters, it should execute the dynamic set of instructions. To create the shared library run make passing ‘shared’ (with out quotes) as a parameter.

The essential flag to note is -fPIC. This flag tells gcc to create place unbiased code which is critical for shared libraries. We didn’t embrace this flag once we constructed the executable program.

We’re going to use the dynamic library shifting ahead. Primarily as a result of on the Mac that is the most typical format. Additionally, if we clear our Go venture later in LiteIDE, it received’t take away the file together with the binary. LiteIDE will take away shared libraries on the decision to scrub.

Let’s create the dynamic library by working the make file:

Screen Shot

We name the make command and it runs the dynamic part of the make file efficiently. As soon as that is accomplished we now have our new dynamic library.

Screen Shot

Now we now have a brand new file in each the DyLib and TestApp folders referred to as libkeyboard.dylib.

One factor I forgot to say is that our dynamic and shared libraries should begin with the letters lib. That is obligatory for issues to work appropriately later. Additionally the library will must be within the working folder for this system to load it once we run this system.

Let’s take a look at the Go supply code file for our take a look at software:

bundle foremost

/*
#cgo CFLAGS: -I../DyLib
#cgo LDFLAGS: -L. -lkeyboard
#embrace <keyboard.h>
*/
import “C”
import (
    “fmt”
)

func foremost() {
    C.InitKeyboard()

    fmt.Printf(“nEnter: “)

    for {
        r := C.GetCharacter()

        fmt.Printf(“%c”, r)

        if r == ‘q’ {
            break
        }
    }

    C.CloseKeyboard()
}

The Go staff has put collectively these two paperwork that specify how Go can incorporate C code straight or use libraries like we’re doing. It’s actually essential to learn these paperwork to higher perceive this Go code:

http://golang.org/cmd/cgo/
http://golang.org/doc/articles/c_go_cgo.html

If you’re binding into C++ libraries, then SWIG (Simplified Wrapper and Interface Generator) is one thing it is advisable take a look at:

http://www.swig.org/
http://www.swig.org/Doc2.0/Go.html

We are going to go away SWIG for one more day. For now let’s break down the Go supply code.

bundle foremost

/*
#cgo CFLAGS: -I../DyLib
#cgo LDFLAGS: -L. -lkeyboard
#embrace <keyboard.h>
*/
import “C”

With a view to present the compiler and linker the parameters it wants, we use these particular cgo instructions. They’re all the time supplied inside a set of feedback and have to be on prime of the import “C” assertion. If there’s a hole between the closing remark and the import command you’re going to get compiler errors.

Right here we’re offering the Go construct course of flags for the compiling and linking of our program. CFLAGS gives parameters to the compiler. We’re telling the compiler it could discover our header information within the SharedLib folder. LDFLAGS present parameters to the linker. We’re offering the linker two parameters, -L (minus capital L) which tells the linker the place it could discover our dynamic library and -l (minus lowercase L) which tells the linker the identify of our library.

Discover once we specify the identify of our library it doesn’t embrace the lib prefix or the extension. It’s anticipated that the library identify begins with lib and ends in both .dylib or the .so extensions.

Final we inform Go to import the seudo-package “C”. This seudo-package gives all of the Go stage assist we have to entry our library. None of that is attainable with out it.

Have a look at how we name into the every of our capabilities from the library:

C.InitKeyboard()
r := C.GetCharacter()
C.CloseKeyboard()

Due to the seudo-package “C” we now have perform wrappers for every perform from the header file. These wrappers deal with the marshaling of information out and in of our capabilities. Discover how we will use a local Go sort and syntax to get the character that’s entered into the keyboard.

Now we will construct the take a look at software and run it from a terminal session:

Screen Shot

Superior. Working like a champ.

Now my son and I can proceed constructing our recreation and get the keyboard motion we have to make the sport actually enjoyable.

It has taken me fairly a number of variety of hours to get a deal with on all of this. There may be nonetheless rather a lot to be taught and assist for this can solely get higher. Sooner or later I’ll take a look at SWIG to include C++ object oriented libraries. For now, having the ability to herald and leverage C libraries is superior.

If you wish to see and entry the code, I’ve put it up within the GoingGo github repository below Keyboard. Have Enjoyable !!

Learn Half II:  Utilizing CGO with Pkg-Config And Customized Dynamic Library Places



RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments