Golang和CGO – 链接到DLL动态库

huangapple go评论85阅读模式
英文:

Golang & CGO – link to a DLL dynamic library

问题

Go语言定位为一种跨平台语言。对我来说,跨平台语言是指可以在所有支持的平台上使用的语言。

我想利用它链接到DLL动态库的能力。DLL库在Windows操作系统上使用,而Golang已知支持Windows操作系统。

Golang的GitHub存储库不允许我在那里发布问题,他们将我重定向到StackOverflow(https://github.com/golang/go/wiki/Questions),所以就这样吧。

该库是用C语言编写的。众所周知,Golang使用所谓的“CGO”功能来支持C语言。

我知道syscall包。我想有意使用“CGO”功能。

我知道Golang提供了一种指定CGO使用的C编译器的方法,使用CC变量。我想知道在Go的CGO中使用CLang编译器(https://en.wikipedia.org/wiki/Clang)的正确方法是什么。

因此,我对Go语言的创建者和维护者有以下问题。

  1. 如何在Go中链接到C语言DLL?
  2. 如何在CGO中使用CLang编译器?
  3. 如何查看CGO中编译和链接过程的输出(C人员的stdout)?

谢谢。

更新

go env -w CC="D:\Program Files\LLVM\bin\clang.exe"

设置C编译器。

go env CC
D:\Program Files\LLVM\bin\clang.exe

但是当我尝试编译一些东西时,它显示:

... build constraints exclude all Go files in ... 

我通过在我的IDE中将环境变量CGO_ENABLED设置为1来修复这个问题。

然后出现了一个新的错误:

cgo: C compiler "D:\\Program" not found: exec: "D:\\Program": file does not exist

看起来Go仍然不支持CC中的空格?!

cmd/go: CC variable misparsed when set to a path containing spaces #41400
https://github.com/golang/go/issues/41400

> @gopherbot gopherbot closed this as completed in 742dcba on Aug 16, 2021.

go version
go version go1.20.3 windows/amd64

我使用原生的go工具为我的CC变量添加了双引号:

go env -w CC="\"D:\Program Files\LLVM\bin\clang.exe\""
go env CC
"D:\Program Files\LLVM\bin\clang.exe"

另一种方法是使用本机Windows工具手动设置变量。

SET CC="D:\Program Files\LLVM\bin\clang.exe"

ECHO %CC%
"D:\Program Files\LLVM\bin\clang.exe"

go env CC
"D:\Program Files\LLVM\bin\clang.exe"

看起来成功了?还没有。

go build .
# test/sdl-wrapper
D:\Program Files\Go\pkg\tool\windows_amd64\link.exe: running D:\Program Files\LLVM\bin\clang.exe failed: exit status 1104
LINK : warning LNK4044: unrecognized option '/-tsaware'; ignored
LINK : warning LNK4044: unrecognized option '/-nxcompat'; ignored
LINK : warning LNK4044: unrecognized option '/-major-os-version=6'; ignored
LINK : warning LNK4044: unrecognized option '/-minor-os-version=1'; ignored
LINK : warning LNK4044: unrecognized option '/-major-subsystem-version=6'; ignored
LINK : warning LNK4044: unrecognized option '/-minor-subsystem-version=1'; ignored
LINK : warning LNK4044: unrecognized option '/-dynamicbase'; ignored
LINK : warning LNK4044: unrecognized option '/-high-entropy-va'; ignored
LINK : warning LNK4044: unrecognized option '/T'; ignored
LINK : warning LNK4044: unrecognized option '/-start-group'; ignored
LINK : warning LNK4044: unrecognized option '/-end-group'; ignored
LINK : fatal error LNK1104: cannot open file 'SDL2.lib'
clang: error: linker command failed with exit code 1104 (use -v to see invocation)

好的。我将SDL2.libSDL2.dll添加到当前文件夹。

go build .
# test/sdl-wrapper
D:\Program Files\Go\pkg\tool\windows_amd64\link.exe: running D:\Program Files\LLVM\bin\clang.exe failed: exit status 1104
LINK : warning LNK4044: unrecognized option '/-tsaware'; ignored
LINK : warning LNK4044: unrecognized option '/-nxcompat'; ignored
LINK : warning LNK4044: unrecognized option '/-major-os-version=6'; ignored
LINK : warning LNK4044: unrecognized option '/-minor-os-version=1'; ignored
LINK : warning LNK4044: unrecognized option '/-major-subsystem-version=6'; ignored
LINK : warning LNK4044: unrecognized option '/-minor-subsystem-version=1'; ignored
LINK : warning LNK4044: unrecognized option '/-dynamicbase'; ignored
LINK : warning LNK4044: unrecognized option '/-high-entropy-va'; ignored
LINK : warning LNK4044: unrecognized option '/T'; ignored
LINK : warning LNK4044: unrecognized option '/-start-group'; ignored
LINK : warning LNK4044: unrecognized option '/-end-group'; ignored
LINK : fatal error LNK1104: cannot open file 'mingwex.lib'
clang: error: linker command failed with exit code 1104 (use -v to see invocation)

我在SDL2库的源代码中没有看到mingwex.lib的任何迹象。
我的代码也没有使用这个文件。
那么这个错误是什么意思?

build: cgo with clang and -buildmode=c-shared failures on Windows #42146
https://github.com/golang/go/issues/42146

我看到一些人向Golang的源代码提交合并请求来修复这个错误。但是这些尝试被Google阻止了。
https://github.com/golang/go/pull/54811

维基百科说
> LLVM目前支持使用各种前端编译Ada、C、C++、D、Delphi、Fortran、Haskell、Julia、Objective-C、Rust和Swift的代码。对LLVM的广泛兴趣导致了为各种语言开发新的前端的几个努力。

维基百科还指出,CLang主要由Apple支持。

我猜现在我知道为什么Google停止了所有使这种语言真正跨平台的尝试。但是...这一点都不聪明。

无论他们是早点还是晚点支持LLVM,否则他们将输掉这场格式之战。

让我们试着挖掘一下,看看这是什么东西

在Golang的源代码中,唯一使用mingwex文本的地方似乎来自src/cmd/link/internal/ld/lib.go文件。这个文件的顶部有一个非常有趣的注释:

// Inferno utils/8l/asm.c
// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/8l/asm.c
//
//	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
//	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
//	Portions Copyright © 1997-1999 Vita Nuova Limited
//	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
//	Portions Copyright © 2004,2006 Bruce Ellis
//	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
//	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
//	Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

好的,我们在这里看到,这个软件是按原样提供的,我们可以随心所欲地使用它。就这样吧。

我正在寻找在跨平台语言Golang中使用的Linux操作系统上的GCC库的硬编码名称。让我们检查一下这个东西。

首先,我的注意力被以下时刻吸引。mingwex不是在常识编程实践中像常量那样使用,而是硬编码分散lib.go文件的不同部分。这非常明显地显示了质量水平。让我们计算一下使用次数。

第一次使用是在函数func loadWindowsHostArchives(ctxt *Link) {的第683行:

if p := ctxt.findLibPath("libmingwex.a"); p != "none" { ... }

第二次使用是在同一个函数的第729行,并在TODO块中进行了注释。

第三次使用是在函数func (ctxt *Link) hostlink() {中,该函数从第1342行开始,到第1902行结束。

在这个庞大的函数中,这个函数几乎1000行长,这里我必须停下来再做一些评论。嗯,使用巨大的函数~1000行长也是质量不好的一个标志。如果你想做一个好的产品-你应该阅读一下C++语言的代码是如何编写的。这只是一个建议。C++被许多程序员认为是世界上最难的编程语言,他们的标准不仅仅是空话...

在这个几乎无法阅读的庞大函数中,mingwex在第1789行被使用:

argv = append(argv, "-Wl,--start-group", "-lmingwex", "-lmingw32", "-Wl,--end-group")

除了这三个地方,mingwex在Golang 1.20.3的源代码中没有被使用。

英文:

Go language positions itself as a cross-platform language. To me a cross-platform language is that kind of language which is usable on all the supported platforms.

I would like to use its ability to link to a DLL dynamic library. DLL libraries are used on Windows operating systems, and Golang is known to support Windows O.S.

Golang's GitHub repository does not allow me to post questions there, they redirect me to StackOverflow (https://github.com/golang/go/wiki/Questions), so let it be so.

The library was written in C language. Golang is known to support the C language using the so called "CGO" feature.

I know about the syscall package. I would like to use the "CGO" feature on purpose.

I know that Golang provides a method to specify a C compiler for CGO using the CC variable. I want to know what is the proper way to use CLang compiler (https://en.wikipedia.org/wiki/Clang) in Go's CGO for my purpose.

So, my questions to the creators and maintainers of the Go language are following.

  1. How do I link to a C language DLL in Go ?
  2. How do I use CLang compiler for CGO ?
  3. How do I see the output (stdout for C people) of the compilation and linkage process in CGO ?

Thank you.

UPDATE

 go env -w CC="D:\Program Files\LLVM\bin\clang.exe"

sets the C compiler.

go env CC
D:\Program Files\LLVM\bin\clang.exe

but when I try to compile something it says:

... build constraints exclude all Go files in ... 

I fix this by setting environment variable CGO_ENABLED to 1 in my IDE.

Then a new error jumps out:

cgo: C compiler "D:\\Program" not found: exec: "D:\\Program": file does not exist

Looks like Go is still not supporting spaces in CC ?!

cmd/go: CC variable misparsed when set to a path containing spaces #41400
https://github.com/golang/go/issues/41400

> @gopherbot gopherbot closed this as completed in 742dcba on Aug 16, 2021.

go version
go version go1.20.3 windows/amd64

I use the native go tool to add double quotes to my CC variable:

go env -w CC="\"D:\Program Files\LLVM\bin\clang.exe\""
go env CC
"D:\Program Files\LLVM\bin\clang.exe"

Alternative way will be to use native Windows tool to set the variable manually.

SET CC="D:\Program Files\LLVM\bin\clang.exe"
ECHO %CC%
"D:\Program Files\LLVM\bin\clang.exe"
go env CC
"D:\Program Files\LLVM\bin\clang.exe"

Looks like success ? Not yet.

go build .
# test/sdl-wrapper
D:\Program Files\Go\pkg\tool\windows_amd64\link.exe: running D:\Program Files\LLVM\bin\clang.exe failed: exit status 1104
LINK : warning LNK4044: unrecognized option '/-tsaware'; ignored
LINK : warning LNK4044: unrecognized option '/-nxcompat'; ignored
LINK : warning LNK4044: unrecognized option '/-major-os-version=6'; ignored
LINK : warning LNK4044: unrecognized option '/-minor-os-version=1'; ignored
LINK : warning LNK4044: unrecognized option '/-major-subsystem-version=6'; ignored
LINK : warning LNK4044: unrecognized option '/-minor-subsystem-version=1'; ignored
LINK : warning LNK4044: unrecognized option '/-dynamicbase'; ignored
LINK : warning LNK4044: unrecognized option '/-high-entropy-va'; ignored
LINK : warning LNK4044: unrecognized option '/T'; ignored
LINK : warning LNK4044: unrecognized option '/-start-group'; ignored
LINK : warning LNK4044: unrecognized option '/-end-group'; ignored
LINK : fatal error LNK1104: cannot open file 'SDL2.lib'
clang: error: linker command failed with exit code 1104 (use -v to see invocation)

OK. I add SDL2.lib and SDL2.dll to the current folder.

go build .
# test/sdl-wrapper
D:\Program Files\Go\pkg\tool\windows_amd64\link.exe: running D:\Program Files\LLVM\bin\clang.exe failed: exit status 1104
LINK : warning LNK4044: unrecognized option '/-tsaware'; ignored
LINK : warning LNK4044: unrecognized option '/-nxcompat'; ignored
LINK : warning LNK4044: unrecognized option '/-major-os-version=6'; ignored
LINK : warning LNK4044: unrecognized option '/-minor-os-version=1'; ignored
LINK : warning LNK4044: unrecognized option '/-major-subsystem-version=6'; ignored
LINK : warning LNK4044: unrecognized option '/-minor-subsystem-version=1'; ignored
LINK : warning LNK4044: unrecognized option '/-dynamicbase'; ignored
LINK : warning LNK4044: unrecognized option '/-high-entropy-va'; ignored
LINK : warning LNK4044: unrecognized option '/T'; ignored
LINK : warning LNK4044: unrecognized option '/-start-group'; ignored
LINK : warning LNK4044: unrecognized option '/-end-group'; ignored
LINK : fatal error LNK1104: cannot open file 'mingwex.lib'
clang: error: linker command failed with exit code 1104 (use -v to see invocation)

I do not see any signs of mingwex.lib in the source codes of SDL2 library.
My code is not using this file also.
What does this error mean then ?

build: cgo with clang and -buildmode=c-shared failures on Windows #42146
https://github.com/golang/go/issues/42146

I saw some people making merge requests to the Golang's source code to fix this mistake. But these attempts are being blocked by Google.
https://github.com/golang/go/pull/54811

Wikipedia says that
> LLVM currently supports compiling of Ada, C, C++, D, Delphi, Fortran, Haskell, Julia, Objective-C, Rust, and Swift using various front ends. Widespread interest in LLVM has led to several efforts to develop new front ends for a variety of languages.

Wikipedia also notes that CLang is primarily supported by Apple.

I guess now I know why Google is stopping all the attempts to make the language really cross-platform. But ... this is not smart at all.

Either they support LLVM sooner or later, or they will lose this war of formats.

Let's try to dig this thing out and see what it is

It looks like the only usage of mingwex text in Golang's source code comes from the src/cmd/link/internal/ld/lib.go file. This file has a super intersting comment in its top:

// Inferno utils/8l/asm.c
// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/8l/asm.c
//
//	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
//	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
//	Portions Copyright © 1997-1999 Vita Nuova Limited
//	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
//	Portions Copyright © 2004,2006 Bruce Ellis
//	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
//	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
//	Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

OK, here we see that this piece of software is provided as is and we can do whatever we want to do with it. Let it be so.

I am searching for a hard-coded name of a GCC library used on Linux O.S. in a cross-platform language Golang, which should be working on Windows O.S. Let's check this thing out.

First of all, my eye sticks to the following moment. The mingwex is not used in constants like in common sense programming practice, but it is hard-coded and scattered across different parts of the lib.go file. This shows the level of quality very distinctly. Let's count the usages.

The first usage is on line 683 in function func loadWindowsHostArchives(ctxt *Link) { :

if p := ctxt.findLibPath("libmingwex.a"); p != "none" { ... }

The second usage is in the same function on line 729 and it is commented in a TODO block.

The third usage is in the function func (ctxt *Link) hostlink() { which starts on line 1342 and ends on line 1902.

Here I must stop and make another comment. Well, usage of gigantic functions ~1000 lines long is also a sign of a bad quality. If you want to make a good product – you should read how code is written in C++ language for example. It is just a piece of advice. C++ is concidered to be the most difficult programming language in the world by many programmers and their standards are more than just words ...

In this gigantic function which is unreadable in practice, mingwex is used on line 1789:

argv = append(argv, "-Wl,--start-group", "-lmingwex", "-lmingw32", "-Wl,--end-group")

Apart from these three places, the mingwex is not used in the source code of Golang 1.20.3.

答案1

得分: 1

  1. 使用cgo ldflags,您可以添加链接标志以与库进行链接,例如:

     // #cgo LDFLAGS: -lpng
    import "C"
    
  2. 使用CC环境变量,参见这个答案

  3. 它只是在go build的标准输出中。

英文:
  1. Using cgo ldflags you can add link flags to link with the library, e.g.

    // #cgo LDFLAGS: -lpng
    import "C"
    
  2. Using the CC environment variable, see this answer.

  3. It is just in the standard output of go build.

huangapple
  • 本文由 发表于 2023年4月10日 00:34:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/75971697.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定