24

Is there a way to build a dll against Go v1.7 under Windows ?

I tried a classic

go build -buildmode=shared main.go

but get

-buildmode=shared not supported on windows/amd64

update Ok, I've got my answer. For those who are interested : https://groups.google.com/forum/#!topic/golang-dev/ckFZAZbnjzU

Stef
  • 3,691
  • 6
  • 43
  • 58
  • 1
    `-buildmode=shared` is a Go shared library, which wouldn't make a DLL anyways. You most likely were looking for `buildmode=c-shared`, though that hasn't been worked on for windows yet, and you can follow [issue #11058](https://golang.org/issue/11058) – JimB Nov 14 '16 at 14:09
  • 2
    Btw, Go 1.10 does support building windows DLLs since update in Oct 10, 2017. `go build -buildmode=c-shared` That single command will generate any DLL for Windows systems. refer to: https://go-review.googlesource.com/c/go/+/69091 – Coconut Nov 23 '18 at 08:28

4 Answers4

27

As of Go 1.10, -buildmode=c-shared is now supported on Windows.

Release notes: https://golang.org/doc/go1.10#compiler

So now compiling to DLL is a one-liner:

go build -o helloworld.dll -buildmode=c-shared

I believe the headers are only compatible with GCC. If you're only exposing C-types, this should not be a big issue. I was able to get LoadLibrary to work in Visual Studio without the header.

Andrew Dolder
  • 386
  • 3
  • 4
  • I get `go: no Go source files` when adding a target OS via `GOOS=windows`. – dthor Dec 09 '21 at 22:29
  • This has nothing to do with my answer. – Andrew Dolder Dec 13 '21 at 12:34
  • Hi. When I load .dll in C++ I get the following error : `fatal error: out of memory allocating heap arena metadata`. Would you mind looking at my question here https://stackoverflow.com/questions/72097599/how-to-use-golangs-c-shared-dll-in-c – Nux May 04 '22 at 08:09
22
go build -buildmode=c-archive github.com/user/ExportHello

====> will build ExportHello.a, ExportHello.h

Take the functions built in ExportHello.a and re-export in Hello2.c

gcc -shared -pthread -o Hello2.dll Hello2.c ExportHello.a -lWinMM -lntdll -lWS2_32

====> will generate Hello2.dll

JimB
  • 104,193
  • 13
  • 262
  • 255
user7155193
  • 221
  • 2
  • 3
13

There is a project on github which shows how to create a DLL, based on, and thanks to user7155193's answer.

Basically you use GCC to build the DLL from golang generated .a and .h files.

First you make a simple Go file that exports a function (or more).

package main

import "C"
import "fmt"

//export PrintBye
func PrintBye() {
    fmt.Println("From DLL: Bye!")
}

func main() {
    // Need a main function to make CGO compile package as C shared library
}

Compile it with:

go build -buildmode=c-archive exportgo.go

Then you make a C program (goDLL.c) which will link in the .h and .a files generated above

#include <stdio.h>
#include "exportgo.h"

// force gcc to link in go runtime (may be a better solution than this)
void dummy() {
    PrintBye();
}

int main() {

}

Compile/link the DLL with GCC:

gcc -shared -pthread -o goDLL.dll goDLL.c exportgo.a -lWinMM -lntdll -lWS2_32

The goDLL.dll then can be loaded into another C program, a freepascal/lazarus program, or your program of choice.

The complete code with a lazarus/fpc project that loads the DLL is here: https://github.com/z505/goDLL

Another Prog
  • 841
  • 13
  • 19
  • These questions are out of scope but please humor me: why do we need (the entire) gcc, and whats the easiest way to get gcc (or presumably just the linker portion?) & get it on path properly? Finally, would llvm tooling (llgo) make this easier? – Groostav Mar 24 '22 at 05:47
0

Just tested on Windows 10 and this works perfectly:

> go version                                                                                     
go version go1.17.2 windows/amd64

> cat main.go
package main

import (
  "C"
)

//export Entry
func Entry(){
  main()
}

func main() {
  // do something
}

> go build -buildmode=c-shared -o mydll.dll main.go
> dumpbin /EXPORTS mydll.dll 
File Type: DLL
..
    ordinal hint RVA      name

          1    0 ...      Entry

> rundll32.exe .\mydll.dll,Entry
binarytrails
  • 516
  • 4
  • 14