在macOS主机上为Windows目标交叉编译golang和cgo

时间:2018-03-26 13:25:15

标签: c++ macos go cross-compiling cgo

我在macOS上并尝试使用从homebrew安装的mingw-w64为Windows编译golang(CGO 1.10)可执行文件。

我的golang包中只有一个函数(SimpleQRDecode)从我的c ++源代码调用其他函数(FindAndDecodeQR,使用zxing c ++端口)。

  1. 编译ZXing源很好(x86_64-w64-mingw32-g ++)
  2. 编译qrcode.cpp很好(x86_64-w64-mingw32-g ++)
  3. 成功将所有对象(zxing + my)合并到静态库(x86_64-w64-mingw32-ar)
  4. 在静态库上成功调用了ranlib(x86_64-w64-mingw32-ranlib)
  5. FAILED 致电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
  6. 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'
    

    qrcode.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

1 个答案:

答案 0 :(得分:1)

这可能不是你想听到的,但在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),
    )
    ...
}

在syscall包的文档中查看更多内容。