Skip to content
/ dllcall Public

Go interface generator to simplify uniform calling of dynamic link libraries in Windows and Linux

License

Notifications You must be signed in to change notification settings

lakal3/dllcall

Repository files navigation

DLLCall tool

DLLCall is an interface generator.

DLLCall will use a single go file as an interface description and from that file it will generate wrappers to call DLL implementing the same interface.

See why DLLCall for comparison between CGO and DLLCall interfaces.

Using DLLCall

Install DLLCall tool using go install github.com/lakal3/dllcall.

You must have at least Go 1.18 to use DLLCall

Invoke: dllcall {interface}.go {c++ interface}.h

Example interface dbif.go

package {package name}

/*
#ctype Stmt *
*/
type stmtHandle uintptr

/*
#cmethod Open
#cmethod Close
*/
type dbIf struct{
	handle stmtHandle
	dbName string	
}

Generate interface

When we invoke dllcall tool such as dllcall dbif.go {otherdir}/dbif.h, dllcall will generate a dbif_impl_windows_amd64.go and dbif_impl_linux_amd64.go file into the current directory and dbif.h to a specified location.

The file name of dbif_impl_{os}_amd64.go is derived from the original go file name. C++ -file can be freely named.

You can use //go:generate directive and go generate command to easily upgrade the interface whenever it changes.

Interface definition

Interface definition must be a single go file containing only type definitions. You can't add functions or methods to the interface file.

Interface usage

After you have generated the interface, you can call it like any other go method

func main()  {
	err := load_dbif("docdbdll.dll") 
	// on Linux:  err := load_dbif(".\libdocdbdll.so") 
	if err != nil { log.Fatal( err )}
	d := &dbIf{ dbName: "test.db"}
	err = d.Open()
	if err != nil { log.Fatal( err )}
	/// ... Do something with db
	err = d.Close()
	if err != nil { log.Fatal( err )}
}

Generator will create an {interface}_impl_{os}_amd64.go file that contains all methods defined with #cmethod.

It will also contain load_{interface} method that takes a single file path to shared library (dll). How libraries are located depends on your operating system.

You must call load_{interface} before you try to invoke any other methods from interface.

Interface implementation

Generator will create a .h-file that you must include into the shared library project.

You must also implement the generated method stubs in a shared library project. In this example the methods to implement are:

GoError *dbIf::Open();
GoError *dbIf::Close();

For more detailed description of comment annotations, generation process and supported types, see generator or examples.

Cgocheck

Go 1.16 introduced new check that prevents pointers structures that contains pointer to Go memory. Dllcall will bypass cgocheck, because generated interface code don't have full type information to support this.

When using dllcall all code must be aware of Go garbage collector and do not retain any references to structure member in C++ side after call has been completed. If you want to keep go allocated heap elements in C++ code you can use new runtime.Pinner available from Go 1.21.

Safe method (experimental)

Added new experimental #csafe_method that mostly allows bypassing Go call overhead to native libraries. This method has several limitations and is experimental. See Generator and new sample fibon for more details.

You should only use fast call when absolutely necessary like accessing high resolution timer in Windows.

In go 1.21.1 safemethod calls will fail because they set new value to SP (Stack pointer). This is due to change in go1.21. It has been fixed in go1.22 for Windows but Linux still. It seems to work in go1.23 for both operating systems

Status

Dllcall is very near release version 1.0. If 0.12.1 don't have any issues it will promoted to version 1.0.0.

Currently only 64 bit (amd64) Windows and 64 bit Linux (amd64) are supported.

TODO?

  • Fastcall (Experimental)
  • Better support for types imported from other modules
  • Linux support
  • Pin example

About

Go interface generator to simplify uniform calling of dynamic link libraries in Windows and Linux

Resources

License

Stars

Watchers

Forks

Languages