Call Go function from VBA via DLL - windows

I'm brand new to Go and am not experienced in compilation issues or with C++. So starting from zero, I'm trying to compile a dll in Go and call a function in VBA. I'm developing the Go in Linux, and switching computers to try it in Windows. The VBA part may not be essential. It does serve as a way for me to test the dll call.
Here's the simple Go code:
package main
import (
"C"
"fmt"
)
func main() {
var x int
x = Test()
fmt.Println(x)
}
func Test() int {
return 666
}
It works for go build, go install, and calling main from the console.
I compile with these two commands, which both run without error, in this order. Should I be running both of them? (I'm way out of my depth here.) The target system is Windows 10, 64 bit with Office 365 ProPlus (but is Excel fundamentally 32 bit?):
env GOOS=windows GOARCH=386 CGO_ENABLED=1 CC=i686-w64-mingw32-gcc go build -buildmode=c-shared -o hello.dll hello.go
env GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc go build -buildmode=c-shared -o hello.dll hello.go
I copy the file, hello.dll, to System32 and in VBA I declare:
Public Declare Function Test Lib "C:\Windows\System32\hello.dll" () as Long
I get the error of Run-time error '53': File Not Found, which I understand may be caused by a missing dependency.
So I run Dependency Walker. This shows me a top level of HELLO.DLL and 4 levels under it of KERNEL32.DLL, MSVCRT.DLL, WINMM.DLL, WS2_32.DLL. And it gives:
Error: At least one required implicit or forwarded depende3ncy was not found.
Warning: At least one delay-load dependency module was not found.
Warning: At least one module has an unresovled import due to a missing export function in a a delay-load dependent module.
There's a huge number of yellow question marks. And dozens of Modules with Error opening file, with names like API-MS-WIN-CORE-... and EXT-MS-WIN-NTUSER-... as well as HVSIFILETRUST.DLL and IESHIMS.DLL and EMCLIENT.DLL
So I've got a few moving parts in my lap and I'm way out of my depth. I'm hoping I'm just missing a simple step (maybe put the dll in a different folder??). If this should be an ambitious or difficult task, I should probably let it go.

Related

Compile Go for windows/arm and arm64 with buildmode=c-shared

I need to compilet a go library via C to a DLL that can be used through PInvoke on ARM/ARM64 Windows. I find many open issues, topics and discussions about this and it sounds like it might partially work. But if I try it like this:
export CC="arm-none-eabi-gcc"
export CXX="arm-none-eabi-g++"
export GOOS="windows"
export GOARCH="arm"
export GOARM=7
export CGO_ENABLED="1"
go build -ldflags="-s -w" -o my_library.dll -buildmode c-shared
I get the result buildmode c-shares is not supported on windows/arm. So it seems to still be not supported.
Another problem is that I need to set CGO_ENABLED and route the compiling through a C/C++-Toolchain as I have to add a C-file generated by SWIG. I tried the above on Ubunu 20.04 with the toolchain of the package gcc-arm-none-eabi.
I'm no C/C++/Go-pro - but the same works for nearly all other platforms like Windows, Linux, Android, Mac and iOS. The latter also is based on ARM64, so I do not really understand why this is not possible - though I value the difficulties with all this.
So, if someone with more in-depth-knowledge can help me here that would be great.
Just to clarifiy: I do not want/need to compile Go itself for ARM/ARM64. I need to compile a Go-program for that platform (to use my library from .Net on e.g. the Surface or a Hololens).
Update from 04.08.2021:
Go 1.17rc2 should include windows arm64 now. And I got the hint to use Zig for cross-compiling. So I've changed my build pipeline to something like this (I'm using Azure Devops in a Ubuntu VM):
go get -v golang.org/dl/go1.17rc2
/home/vsts/go/bin/go1.17rc2 download
/home/vsts/go/bin/go1.17rc2 version
sudo snap install zig --classic --beta
zig version
export CC="zig cc -target aarch64-windows-gnu"
export CXX="zig c++ -target aarch64-windows-gnu"
export GOOS="windows"
export GOARCH="arm64"
export GOARM=7
export CGO_ENABLED="1"
/home/vsts/go/bin/go1.17rc2 build -ldflags="-s -w" -o storj_uplink.dll -buildmode c-shared -tags extended
I then get this error:
2021-08-03T19:24:52.0641737Z # runtime/cgo
2021-08-03T19:24:52.0642803Z info: Usage: zig [command] [options]
2021-08-03T19:24:52.0643335Z
2021-08-03T19:24:52.0643827Z Commands:
2021-08-03T19:24:52.0643940Z
2021-08-03T19:24:52.0644276Z build Build project from build.zig
2021-08-03T19:24:52.0645203Z init-exe Initialize a `zig build` application in the cwd
2021-08-03T19:24:52.0645768Z init-lib Initialize a `zig build` library in the cwd
2021-08-03T19:24:52.0645950Z
2021-08-03T19:24:52.0646407Z ast-check Look for simple compile errors in any set of files
2021-08-03T19:24:52.0646936Z build-exe Create executable from source or object files
2021-08-03T19:24:52.0647468Z build-lib Create library from source or object files
2021-08-03T19:24:52.0647994Z build-obj Create object from source or object files
2021-08-03T19:24:52.0648390Z fmt Reformat Zig source into canonical form
2021-08-03T19:24:52.0648753Z run Create executable and run immediately
2021-08-03T19:24:52.0649088Z test Create and run a test build
2021-08-03T19:24:52.0649551Z translate-c Convert C code to Zig code
2021-08-03T19:24:52.0649707Z
2021-08-03T19:24:52.0650109Z ar Use Zig as a drop-in archiver
2021-08-03T19:24:52.0650576Z cc Use Zig as a drop-in C compiler
2021-08-03T19:24:52.0651070Z c++ Use Zig as a drop-in C++ compiler
2021-08-03T19:24:52.0651549Z dlltool Use Zig as a drop-in dlltool.exe
2021-08-03T19:24:52.0652033Z lib Use Zig as a drop-in lib.exe
2021-08-03T19:24:52.0652495Z ranlib Use Zig as a drop-in ranlib
2021-08-03T19:24:52.0652670Z
2021-08-03T19:24:52.0652962Z env Print lib path, std path, cache directory, and version
2021-08-03T19:24:52.0653531Z help Print this help and exit
2021-08-03T19:24:52.0653879Z libc Display native libc paths file or validate one
2021-08-03T19:24:52.0654250Z targets List available compilation targets
2021-08-03T19:24:52.0654579Z version Print version number and exit
2021-08-03T19:24:52.0655062Z zen Print Zen of Zig and exit
2021-08-03T19:24:52.0655220Z
2021-08-03T19:24:52.0655445Z General Options:
2021-08-03T19:24:52.0655565Z
2021-08-03T19:24:52.0655982Z -h, --help Print command-specific usage
2021-08-03T19:24:52.0656154Z
2021-08-03T19:24:52.0656502Z error: unknown command: -E
2021-08-03T19:25:03.2047129Z # golang.org/x/sys/windows
2021-08-03T19:25:03.2048568Z /home/vsts/go/pkg/mod/golang.org/x/sys#v0.0.0-20210112091331-59c308dcf3cc/windows/types_windows.go:1620:24: undefined: JOBOBJECT_BASIC_LIMIT_INFORMATION
2021-08-03T19:25:03.2049594Z /home/vsts/go/pkg/mod/golang.org/x/sys#v0.0.0-20210112091331-59c308dcf3cc/windows/zsyscall_windows.go:3020:38: undefined: WSAData
2021-08-03T19:25:03.2050606Z /home/vsts/go/pkg/mod/golang.org/x/sys#v0.0.0-20210112091331-59c308dcf3cc/windows/zsyscall_windows.go:3096:51: undefined: Servent
2021-08-03T19:25:03.2051572Z /home/vsts/go/pkg/mod/golang.org/x/sys#v0.0.0-20210112091331-59c308dcf3cc/windows/zsyscall_windows.go:3110:50: undefined: Servent
2021-08-03T19:25:04.7947309Z ##[error]Bash exited with code '1'.
Basically "unknown command: -E" which is described here. But from my understanding this should work already. And furthermore this blog post does it directly with zig, too.
Second update from 04.08.2021
Go is now calling zig! The workaround using a bash-script is working. Now I get the following error:
2021-08-04T11:54:47.2530981Z # golang.org/x/sys/windows
2021-08-04T11:54:47.2532284Z /home/vsts/go/pkg/mod/golang.org/x/sys#v0.0.0-20210112091331-59c308dcf3cc/windows/types_windows.go:1620:24: undefined: JOBOBJECT_BASIC_LIMIT_INFORMATION
2021-08-04T11:54:47.2533180Z /home/vsts/go/pkg/mod/golang.org/x/sys#v0.0.0-20210112091331-59c308dcf3cc/windows/zsyscall_windows.go:3020:38: undefined: WSAData
2021-08-04T11:54:47.2534002Z /home/vsts/go/pkg/mod/golang.org/x/sys#v0.0.0-20210112091331-59c308dcf3cc/windows/zsyscall_windows.go:3096:51: undefined: Servent
2021-08-04T11:54:47.2534797Z /home/vsts/go/pkg/mod/golang.org/x/sys#v0.0.0-20210112091331-59c308dcf3cc/windows/zsyscall_windows.go:3110:50: undefined: Servent
2021-08-04T11:54:57.4223210Z # runtime/cgo
2021-08-04T11:54:57.4224911Z /snap/zig/3678/lib/libc/mingw/secapi/vsprintf_s.c:39:10: warning: implicit declaration of function '__ms_vsnprintf' is invalid in C99 [-Wimplicit-function-declaration]
2021-08-04T11:54:57.4225714Z return __ms_vsnprintf (_DstBuf, _Size, _Format, _ArgList);
2021-08-04T11:54:57.4226223Z ^
2021-08-04T11:54:57.4226624Z 1 warning generated.
2021-08-04T11:54:57.4227534Z /snap/zig/3678/lib/libc/mingw/math/arm/s_trunc.c/snap/zig/3678/lib/libc/mingw/math/arm/s_truncf.c:24:10: fatal error: '../bsd_private_base.h' file not found
2021-08-04T11:54:57.4228188Z #include "../bsd_private_base.h"
2021-08-04T11:54:57.4228651Z ^~~~~~~~~~~~~~~~~~~~~~~
2021-08-04T11:54:57.4229332Z :26:10: fatal error: '../bsd_private_base.h' file not found
2021-08-04T11:54:57.4229850Z #include "../bsd_private_base.h"
2021-08-04T11:54:57.4230310Z ^~~~~~~~~~~~~~~~~~~~~~~
2021-08-04T11:54:57.4230966Z 1 error generated.
2021-08-04T11:54:57.4231397Z 1 error generated.
2021-08-04T11:54:57.4522549Z ##[error]Bash exited with code '1'.
Update from 05.08.2021:
I finally found a toolchain that at least does not throw an error. But now it quits silently without generating a DLL. Not sure what happens now, though. This is my call:
go get -v golang.org/dl/go1.17rc2
/home/vsts/go/bin/go1.17rc2 download
/home/vsts/go/bin/go1.17rc2 version
wget https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-arm-none-linux-gnueabihf.tar.xz
tar -xf gcc-arm-10.3-2021.07-x86_64-arm-none-linux-gnueabihf.tar.xz
cd gcc-arm-10.3-2021.07-x86_64-arm-none-linux-gnueabihf
cd bin
export PATH=$PATH:$(pwd)
cd ..
cd ..
cd uplink-c
export CC="arm-none-linux-gnueabihf-gcc -v"
export CXX="arm-none-linux-gnueabihf-g++ -v"
export GOOS="windows"
export GOARCH="arm64"
export GOARM=7
export CGO_ENABLED="1"
home/vsts/go/bin/go1.17rc2 build -ldflags="-s -w" -o storj_uplink.dll -buildmode c-shared -tags extended -v
I do not want/need to compile Go itself for ARM/ARM64. I need to compile a Go-program for that platform
That should work, using Go 1.17 beta
Its documentation do mention:
Windows
Go 1.17 adds support of 64-bit ARM architecture on Windows (the windows/arm64 port).
This port supports cgo.
The OP topperdel refers in the comments to CL 326310:
cmd/internal/sys: mark windows/arm64 as c-shared-capable
The platform supports c-shared now, so flip this on.
I've given this a small smoke test using WireGuard Tunnel Library, and it was able to pass packets and generally function well.
Since the WireGuard Tunnel Library uses quite a bit of Go functionality under the hood, I think it's a decent test that a lot of things that should be working are working. So this commit enables it.
In order to get all tests passing, we make a few small changes, such as
passing -Wno-dll-attribute-on-redeclaration to clang and avoiding
loading shared libraries into Powershell on arm.
As illustrated by those issues, this is this is still a work in progress:
issue 46502 ("runtime: several tests are failing on windows-arm64-aws builder due to redeclaration warnings (upgraded to errors in testing)"),
issue 46701 ("Powershell on arm64/arm cannot load arm64/arm binaries because it is an intel process")
The test part is now (June 13th, 2021) closed with golang/go commit 1ed0d12:
runtime: testprogcgo: don't call exported Go functions directly from Go
Instead route through a C function, to avoid declaration conflicts
between the declaration needed in the cgo comment and the declaration
generated by cgo in _cgo_export.h.
This is not something user code will ever do, so no need to make it
work in cgo.
I mentioned in the comments
From ziglang/zig issue 7342, zig should be supported now.
Example, with Go 1.17 : "Zig Makes Go Cross Compilation Just Work" from Loris Cro (VP of community #ziglang):
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 \
CC="zig cc -target x86_64-linux" \
CXX="zig c++ -target x86_64-linux" \
go build --tags extended
You would need to adapt the arch targets to your need
Note: a bash shell session is needed. So git bash on Windows, for instance.

Why does Go source contain many .go files? How do they get compiled?

i want know how go compiler work!
https://github.com/golang/go
this source Contains 88% .go file.
so this should be have another compiler to execute .go file.
Example : https://github.com/golang/go/blob/964639cc338db650ccadeafb7424bc8ebb2c0f6c/src/go/ast/ast.go
Golang use what compiler for final Generate Execute file?! and where available they source?
may be Golang generate a c code and next use GCC or ...?
New Update
i not want go1.4 then in using c.
88% source of github.com/golang/go is .go file. what compile .go file at Go Source? i want see Final GO Compiler?
https://github.com/golang/go/search?l=c
i think this called cg.
mean An old version of Go compiler (version 1.4) is used to compile newer version of Go compiler.???!
go-go1.4.3/src/go/token/token.go this is go token,lexer and is write at GO
FUNC: "func",
GO: "go",
GOTO: "goto",
IF: "if",
IMPORT: "import",
so where main compiler for execute .go file?
go-go1.4.3/src/runtime/compiler.go
// Copyright 2012 The Go Authors. All rights reserved.
package runtime
// Compiler is the name of the compiler toolchain that built the
// running binary. Known toolchains are:
//
// gc The 5g/6g/8g compiler suite at code.google.com/p/go.
// gccgo The gccgo front end, part of the GCC compiler suite.
//
const Compiler = "gc"
go-go1.4.3/src/cmd/gc$ make
go tool dist install -v
make: go: Command not found
../../Make.dist:13: recipe for target 'install' failed
make: *** [install] Error 127
make gc why need Go?!
Last version of GO Language how work?! mean how this generate a output for cross platform? this use generate code to C and then use c compiler?
According to https://golang.org/doc/go1.5#implementation and https://www.infoq.com/news/2015/01/golang-15-bootstrapped , Go was originally implemented in C but became self-hosted at version 1.5. Bootstrapping is the process of compiling a compiler with itself. The Go developers wrote a C -> Go transpiler to convert the original C compiler to Go, then they hand-edited the Go code to make it idiomatic.

GCC unable to compile Go Program

I wrote a very simple program in Go using using a 2D game library.
package main
import (
"github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/ebitenutil"
)
const screenWidth, screenHeight = 320, 240
func update(screen *ebiten.Image) error {
ebitenutil.DebugPrint(screen, "Game test")
return nil;
}
func main() {
if err := ebiten.Run(update, screenWidth, screenHeight, 2, "Test"); err != nil {
panic(err)
}
}
This, however, relies on GCC to compile. When running, I'm prompted with this message:
# github.com/go-gl/glfw/v3.2/glfw
cc1.exe: sorry, unimplemented: 64-bit mode not compiled in
# github.com/go-gl/gl/v2.1/gl
cc1.exe: sorry, unimplemented: 64-bit mode not compiled in
I attempted to download MinGW-w64 to rectify the issue, but it hasn't been successful.
How would I go about resolving this?
So your C compiler does not support 64 bit compilation. One way to resolve this is to build in 32 bit mode. Go will by default try to build for the system architecture that you are on but you can modify that behavior by setting the environment variable GOARCH=386 before building. On Windows you can type this into your cmd:
set GOARCH=386
go build
You could create a simple .bat batch script with this content and run that when you want to build.
Note that 64 bit systems will run 32 bit programs just fine. This is also a nice way to make sure that when you give the .exe to someone else, it will run on their system (not considering other dependencies).
If you want to upgrade your C compiler instead to build 64 bit applications, see this SO thread, maybe that helps.

cannot implicitly include runtime/cgo in a shared library

Following my earlier question, now I'm getting this error when trying to perform all the same steps from this article, since I've upgraded from Go 1.6.1 to Go 1.7.1 (I cannot go back to Go 1.6.1 because the linker crashes when tries to compile some shared libraries).
What I did:
Installed go in ~/.go/go (this is later referred to as GOROOT).
Compiled libstd.so:
GOROOT=~/.go/go GOPATH=~/tests go install -buildmode=shared -linkshared std
Compiled calc library:
GOROOT=~/.go/go GOPATH=~/tests go install -a -x -buildmode=shared -linkshared calc
Tried to compile app:
GOROOT=~/.go/go GOPATH=~/tests go build -a -x -linkshared -o app cashier
and received this error:
~/.go/go/pkg/tool/linux_amd64/link: cannot implicitly include runtime/cgo in a shared library
I tried to repeat the steps with CGO_ENABLED=0 prepended to the environment, but nothing would build this way. Giving me this error:
imports runtime/cgo: C source files not allowed when not using cgo or SWIG: gcc_fatalf.c gcc_linux_amd64.c gcc_mmap.c gcc_util.c
Is this a known bug? Is making shared libraries meant to be supported?
The only way I've been able to make working DLLs is to use buildmode=c-archive and write C stubs for all the go functions I want to export. But I was working on Windows for this, I haven't had to mess with this on Linux. It is a path to investigate.

How to link go package in Xcode CoreFoundation project?

My goal is to be able to call Go functions from a Cocoa project but I just started with a pure C CoreFoundation project.
Here is my simple go package:
package hello
import "C"
import (
"fmt"
)
//export SayHello
func SayHello() {
fmt.Println("Hello, World!")
}
I build this using go install which generates the lib hello.a.
I want to be able to link this library to my CoreFoundation project so I can call SayHello from my C code.
Doing this causes Xcode to show a warning stating that hello.a was ignored because it wasn't build for the X86_64 architecture.
I can tell that the issue most likely is due to the fact that the way the Go code was compiled is not compatible with the way XCode is compiling the CoreFoundation project.
Therefore my question is: Is it possible to somehow compile my Go package in a way which is linkable with my CoreFoundation project?
You can't link a Go library into a C program. The *.a archives that go outputs are not the same format as C object files so the C compiler won't know how to link them in.
The *.a files folow the format described here: http://golang.org/cmd/pack/ and here: http://plan9.bell-labs.com/magic/man2html/1/ar
CGO allows C to call go functions and vice versa but That will require the main app to be a Go binary not a C binary in order for the linking to work correctly.

Resources