Using cgo to call C code from within Go code

I lack a deep understanding of how C works, but I wanted to call some of the functions within the pdh.dll Windows library from my Go code. I explored a few rabbit holes, so I figured I would post how I got this working. If you want to skip to running my examples on your own, you can download them here.

First off, if you don’t know anything about cgo (like myself) then I recommend learning the basics by reading C? Go? Cgo!

Before running any code using cgo or gcc you have to have gcc installed on your machine. I found the easiest install method to be tdm-gcc. Simply download the file corresponding to the architecture of your machine then run it.

Including a Windows Library

In my example code, pdh.go demonstrates what I set out to do. Here is the code:

package pdh

// #cgo LDFLAGS: -L./lib -lpdh
// #include <pdh.h>
import "C"

func PdhValidatePath(path string) uint32 {
    ret := C.PdhValidatePath(C.CString(path))
    return uint32(ret)
}

// #cgo LDFLAGS: -L./lib -lpdh tells the gcc compiler to look for the pdh library within the standard lib directory (note that this directory is not within the Go project directory).

// #include <pdh.h> tells the gcc compiler to include pdh.h. This means that all of the functions within pdh.h can be called using C.<function name>. An example of this is shown by the line ret := C.PdhValidatePath(C.CString(path))

Including Your Own C

If you want to write your own C class, then I recommend taking a look at the package named increment within my example. In the package directory you can see increment.c and increment.h. These files were translated into increment.lib by running the following commands:

gcc -O2 -c increment.c
ar q increment.lib increment.o

Since increment.lib and increment.h exist within the package directory, they can be referenced with just a simple #include statement as shown here:

package increment

// #include <increment.h>
import "C"

func Increment(i int) int{
   return int(C.x(C.int(i)))
}

Including a Standard Library With Custom C Code

My package titled stdlib demonstrates how to include a standard library with custom C code that references that standard library.

package stdlib

/*
#include 
#include 

void myprint(char* s) {
	printf("%s\n", s);
}
*/
import "C"

import "unsafe"

func PrintText() {
	cs := C.CString("Hello from stdio\n")
	C.myprint(cs)
	C.free(unsafe.Pointer(cs))
}

func Random() int {
	return int(C.rand())
}

func Seed(i int) {
	C.srand(C.uint(i))
}

In this code, you can see that there is a C function called myprint that is defined in the cgo preample. The myprint function can be used to print text using the stdio printf function. This is a pretty simple example, but it is a good starting point for anyone that has a reason to write code in C rather than Go.

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s