
Go 1.10+ supports building Windows DLLs via -buildmode=c-shared, enabling seamless interop with C/C++ applications—no MSVC header dependency required if only C-compatible types are exposed.
go 1.10+ supports building windows dlls via `-buildmode=c-shared`, enabling seamless interop with c/c++ applications—no msvc header dependency required if only c-compatible types are exposed.
Starting with Go 1.10, Windows gained official support for c-shared build mode—making it possible to generate native Windows DLLs directly from Go code. This is a significant improvement over Go 1.7 (and earlier), where -buildmode=shared was explicitly unsupported on windows/amd64, as the original question correctly observed.
To build a DLL, use:
go build -o helloworld.dll -buildmode=c-shared main.go
This command produces two artifacts:
-
helloworld.dll: The loadable dynamic library. -
helloworld.h: A C header declaring exported functions (e.g.,void Hello(void)), generated automatically and compatible with GCC-based toolchains (e.g., MinGW-w64).
⚠️ Important notes:
- Your Go source must export functions using
//exportcomments and declare them withC-compatible signatures (e.g., no Go slices, maps, or structs with unexported fields). Only basic types (int,char*,void*) and C-style structs are safe. - While the generated
.hfile is designed for GCC, you can load the DLL in Visual Studio without it—usingLoadLibraryandGetProcAddress—as long as your Go exports adhere strictly to C ABI conventions. - The
mainpackage is required (not a library package), and must includeimport "C"and at least one//export-annotated function.
Example main.go:
package main
import "C"
import "fmt"
//export Hello
func Hello() {
fmt.Println("Hello from Go DLL!")
}
//export Add
func Add(a, b int) int {
return a + b
}
func main() {} // required, but not executed when loaded as DLLAfter building, you can call Add from C++ like this:
#include <windows.h>
#include <iostream>
typedef int (*AddFunc)(int, int);
int main() {
HMODULE h = LoadLibrary(L"helloworld.dll");
if (h) {
AddFunc add = (AddFunc)GetProcAddress(h, "Add");
if (add) std::cout << add(3, 4) << "\n"; // prints 7
FreeLibrary(h);
}
}In summary: Go 1.7 cannot produce Windows DLLs—but Go 1.10+ makes it straightforward and production-ready, provided you follow C-interop constraints. Always test exported functions with go test and validate calling conventions across your target toolchain.

















