CGO链接错误:未定义对“ MemoryFreeLibrary”的引用

I am trying to wrap around a C library with Go. The library is built with CMake and produces a static library file. I added the #cgo stuff at the beginning of the .go file with the proper CFLAGS and LDFLAGS, however, I keep getting undefined reference errors when running go build memorymodule.go.

Here is my code:

package main

/*
#cgo CFLAGS: -IMemoryModule
#cgo LDFLAGS: MemoryModule/build/MemoryModule.a
#include "MemoryModule/MemoryModule.h"
*/
import "C"

import (
    "fmt"
    "io/ioutil"
    "os"
    "unsafe"
)

const SIZE int = 1024

func end(msg string) {
    fmt.Println(msg)
    os.Exit(1)
}

func check(err error, msg string) {
    if err != nil {
        end(msg)
    }
}

func main() {

    bin, err := ioutil.ReadFile(os.Args[0])
    check(err, "error reading file")

    // Convert the args passed to this program into a C array of C strings
    var cArgs []*C.char
    for _, goString := range os.Args {
        cArgs = append(cArgs, C.CString(goString))
    }

    // Load the reconstructed binary from memory
    handle := C.MemoryLoadLibraryEx(
        unsafe.Pointer(&bin[0]),                // void *data
        (C.size_t)(len(bin)),                   // size_t
        (*[0]byte)(C.MemoryDefaultAlloc),          // Alloc func ptr
        (*[0]byte)(C.MemoryDefaultFree),           // Free func ptr
        (*[0]byte)(C.MemoryDefaultLoadLibrary),    // loadLibrary func ptr
        (*[0]byte)(C.MemoryDefaultGetProcAddress), // getProcAddress func ptr
        (*[0]byte)(C.MemoryDefaultFreeLibrary),    // freeLibrary func ptr
        unsafe.Pointer(&cArgs[0]),                 // void *userdata
    )

    // Execute binary
    C.MemoryCallEntryPoint(handle)

    // Cleanup
    C.MemoryFreeLibrary(handle)

}

Here is the results from the go build ... with -x to help with debugging:

cd /home/wlaw/go-memory-module
i686-w64-mingw32-gcc -I . -m32 -mthreads -fmessage-length=0 -fdebug-prefix-map=$WORK=/tmp/go-build -gno-record-gcc-switches -o $WORK/command-line-arguments/_obj/_cgo_.o $WORK/command-line-arguments/_obj/_cgo_main.o $WORK/command-line-arguments/_obj/_cgo_export.o $WORK/command-line-arguments/_obj/memorymodule.cgo2.o -g -O2 MemoryModule/build/MemoryModule.a
# command-line-arguments
/tmp/go-build590803163/command-line-arguments/_obj/_cgo_main.o:_cgo_main.c:(.data+0x0): undefined reference to `MemoryDefaultLoadLibrary'
/tmp/go-build590803163/command-line-arguments/_obj/_cgo_main.o:_cgo_main.c:(.data+0x4): undefined reference to `MemoryDefaultGetProcAddress'
/tmp/go-build590803163/command-line-arguments/_obj/_cgo_main.o:_cgo_main.c:(.data+0x8): undefined reference to `MemoryDefaultFreeLibrary'
/tmp/go-build590803163/command-line-arguments/_obj/_cgo_main.o:_cgo_main.c:(.data+0xc): undefined reference to `MemoryDefaultFree'
/tmp/go-build590803163/command-line-arguments/_obj/_cgo_main.o:_cgo_main.c:(.data+0x10): undefined reference to `MemoryDefaultAlloc'
/tmp/go-build590803163/command-line-arguments/_obj/memorymodule.cgo2.o: In function `cgo_50ced23471ff_Cfunc_MemoryCallEntryPoint':
/tmp/go-build/command-line-arguments/_obj/cgo-gcc-prolog:40: undefined reference to `MemoryCallEntryPoint'
/tmp/go-build590803163/command-line-arguments/_obj/memorymodule.cgo2.o: In function `cgo_50ced23471ff_Cfunc_MemoryLoadLibraryEx':
/tmp/go-build/command-line-arguments/_obj/cgo-gcc-prolog:76: undefined reference to `MemoryLoadLibraryEx'
/tmp/go-build590803163/command-line-arguments/_obj/memorymodule.cgo2.o: In function `cgo_50ced23471ff_Cfunc_MemoryFreeLibrary':
/tmp/go-build/command-line-arguments/_obj/cgo-gcc-prolog:54: undefined reference to `MemoryFreeLibrary'
collect2: error: ld returned 1 exit status
Makefile:9: recipe for target 'all' failed
make: *** [all] Error 2

Whats interesting is if I compile the MemoryModule dependency using make instead of CMake (by editing my Makefile) such that it produces an object file instead of a static library file, and modify my source code to link with that instead, I get no problems:

package main

/*
#cgo CFLAGS: -IMemoryModule
#cgo LDFLAGS: MemoryModule/MemoryModule.o
#include "MemoryModule/MemoryModule.h"
*/
import "C"
...

My Makefile for reference:

ifneq ("$(shell which i686-w64-mingw32-gcc)","")
compiler = i686-w64-mingw32-gcc
else
compiler = i586-mingw32msvc-gcc
endif

# Build the dependencies first (subdirs), then move onto the meat and potatoes.
all: MemoryModule
    CC=$(compiler) CGO_ENABLED=1 GOOS=windows GOARCH=386 go build -x memorymodule.go

# Dependency build. 
SUBDIRS = MemoryModule
subdirs: $(SUBDIRS)
$(SUBDIRS):
    $(MAKE) -C $@
# Override default subdir build behavior (make) with cmake. 
MemoryModule:
    [ "`ls -A MemoryModule`" ] || git submodule update --init
    # $(MAKE) -C $@
    cmake -HMemoryModule -BMemoryModule/build
    cmake --build MemoryModule/build --target MemoryModule

# Clean targed. 
CLEANDIRS = $(SUBDIRS:%=clean-%)
clean: $(CLEANDIRS)
    rm -f memorymodule.exe
$(CLEANDIRS): 
    $(MAKE) -C $(@:clean-%=%) clean

test:
    $(MAKE) -C tests test

.PHONY: subdirs $(INSTALLDIRS) $(SUBDIRS) clean test

Any help would be appreciated!

Git project here: https://github.com/wheelerlaw/go-memory-module

Update:

Okay, so I stumbled across this SO question. So if I change my go build command to:

GOOS="windows" GOARCH="amd64" CGO_ENABLED="1" CC="x86_64-w64-mingw32-gcc" go build -x

from:

GOOS="windows" GOARCH="386" CGO_ENABLED="1" CC="i686-w64-mingw32-gcc" go build -x

... it works. So it looks like an incompatibility between the different archs. I'm going to download a 32 bit version of Go to see if that helps.

But what I don't understand is that the program compiles just fine even with the mis-matched archs when I compile C library into an object instead of a static library. Any ideas?

cgo
duanke1984
duanke1984 嗯,这很有趣,但是由于我正在交叉编译,因此他们的关闭CGO的建议在我的情况下不起作用。请参阅我的问题以获取更新,我想我可能已经找到了为什么不进行编译的原因,但我不确定。
2 年多之前 回复
duanchi4544
duanchi4544 这可以帮助stackoverflow.com/questions/16747021/…
2 年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐