我在 macOS 上,尝试使用从自制程序安装的 mingw-w64 交叉编译适用于 Windows 的 golang (CGO 1.10) 可执行文件。
我的 golang 包只有一个函数(SimpleQRDecode),它从我的 c++ 源调用其他函数(FindAndDecodeQR,使用 zxing c++ 端口)。
CGO_ENABLED=1 CXX="x86_64-w64-mingw32-g++" CXX_FOR_TARGET="x86_64-w64-mingw32-g++" CC="x86_64-w64-mingw32-gcc" CC_FOR_TARGET="x86_64-w64-mingw32-gcc" GOOS=windows GOARCH=amd64 go build -x
go build
输出包含大量未解析的符号消息,例如
libmyqr.a(qrcode.o):qrcode.cpp:(.text+0x79): undefined reference to `operator new(unsigned long long)'
libmyqr.a(qrcode.o):qrcode.cpp:(.text+0x2cb): undefined reference to `std::string::length() const'
libmyqr.a(qrcode.o):qrcode.cpp:(.text+0x4a7): undefined reference to `__cxa_begin_catch'
libmyqr.a(BinaryBitmap.cpp.obj):BinaryBitmap.cpp:(.text+0x5c2): undefined reference to `std::ios_base::Init::~Init()'
libmyqr.a(BinaryBitmap.cpp.obj):BinaryBitmap.cpp:(.xdata+0xc): undefined reference to `__gxx_personality_seh0'
二维码.go:
package qrcode
/*
#cgo CFLAGS: -I../../native/prefix/include -I../../libmyqr -fPIC
#cgo CXXFLAGS: -I../../native/prefix/include -I../../libmyqr -fPIC
#cgo LDFLAGS: -L../../libmyqr -lmyqr -lstdc++
#include <stdlib.h>
#include <qrcode.h>
*/
import "C"
import (
"errors"
"fmt"
"unsafe"
)
func SimpleQRDecode(rasterData []byte, width, height int) (string, bool, error) {
res := C.FindAndDecodeQR((*C.char)(unsafe.Pointer(&data[0])), C.int(len(data)), C.int(width), C.int(height))
qrcode.h:
#ifdef __cplusplus
extern "C" {
#endif
const char* FindAndDecodeQR(char *raster, int size, int width, int height);
#ifdef __cplusplus
}
#endif
qrcode.cpp:
#include "qrcode.h"
#include <sstream>
#include <zxing/ZXing.h>
#include <zxing/Binarizer.h>
#include <zxing/BinaryBitmap.h>
#include <zxing/Result.h>
#include <zxing/qrcode/QRCodeReader.h>
#include <zxing/common/GreyscaleRotatedLuminanceSource.h>
#include <zxing/common/GlobalHistogramBinarizer.h>
const char* FindAndDecodeQR(char *raster, int size, int width, int height) {
// GreyscaleLuminanceSource
std::ostringstream resStream;
try {
zxing::ArrayRef<char> image(raster, size);
zxing::Ref<zxing::GreyscaleRotatedLuminanceSource> source(new zxing::GreyscaleRotatedLuminanceSource(image, width, height, 0, 0, width, height));
libmyqr.a - 由所有 zxing 编译对象 + qrcode.cpp.o 组成的静态库
这可能不是您想听到的,但在 Mac 上交叉编译到 Windows 的最简单方法是从您的
c/c++
代码构建 DLL 库,并从您的 go
代码处理该 DLL 库。在这种情况下,你甚至不需要CGO_ENABLED=1
。
go
代码可以如下所示(未经测试):
// +build windows
package qrcode
import (
"errors"
"fmt"
"syscalls"
"unsafe"
)
var modYourPkg = syscall.NewLazyDLL("yourpkg.dll")
var procFindAndDecodeQR = modYourPkg.NewProc("FindAndDecodeQR")
func SimpleQRDecode(rasterData []byte, width, height int) (string, bool, error) {
res, _, _ := procFindAndDecodeQR.Call(
uintptr(unsafe.Pointer(&rasterData[0])),
uintptr(len(data)),
uintptr(width),
uintptr(height),
)
...
}
请参阅系统调用包的文档了解更多信息。
MinGW 在静态链接时可能有点愚蠢。尝试使用外部链接器。修改你的 go build 命令如下:
CGO_ENABLED=1 GOOS=windows GOARCH=amd64 go build -x -ldflags "-linkmode=external -extldflags -static"
这告诉 MinGW 使用外部链接器(我想它会自动尝试找到一个构建系统)并为其提供 -static 参数。
您还可以尝试将 CGO LDFLAGS 提供给外部链接器,以便它可以找到它们。我猜 MinGW 会自动为你做这件事。