如何在windows x86-64上将Golang包链接到现有的C项目(使用Go from C)

tvmytwxo  于 2023-01-18  发布在  Go
关注(0)|答案(2)|浏览(112)

如何使用Golang从C代码生成的libgolang.a构建C可执行文件:test.exe
这些命令在Ubuntu x86 - 64中进行可执行二进制"测试",并且工作正常(但在Windows x86 - 64中不是这样):

go build -buildmode c-archive -o libgolang.a
gcc -o test _main.c libgolang.a -lpthread

与:
这是main.go文件:

package main

import "C"
import "fmt"

//export Add
func Add(a, b uint64) uint64 {
    return a + b
}

func main() {
    fmt.Println("Hi")
}

这是_main.c文件:

#include <stdio.h>
#include <stdint.h>
#include "libgolang.h"

int main()
{
    uint64_t a=10;
    uint64_t b=20;
    uint64_t c=Add(a,b);
    printf("%ld\n",c);
    return 0;
}

在Windows中,此命令:

go build -buildmode c-archive -o libgolang.a

运行正常,并生成libgolang.alibgolang.h文件。libgolang.h

/* Created by "go tool cgo" - DO NOT EDIT. */

/* package github.com/ARamazani/go/DLL */

/* Start of preamble from import "C" comments.  */



/* End of preamble from import "C" comments.  */

/* Start of boilerplate cgo prologue.  */

#ifndef GO_CGO_PROLOGUE_H
#define GO_CGO_PROLOGUE_H

typedef signed char GoInt8;
typedef unsigned char GoUint8;
typedef short GoInt16;
typedef unsigned short GoUint16;
typedef int GoInt32;
typedef unsigned int GoUint32;
typedef long long GoInt64;
typedef unsigned long long GoUint64;
typedef GoInt64 GoInt;
typedef GoUint64 GoUint;
typedef __SIZE_TYPE__ GoUintptr;
typedef float GoFloat32;
typedef double GoFloat64;
typedef float _Complex GoComplex64;
typedef double _Complex GoComplex128;

/*
  static assertion to make sure the file is being used on architecture
  at least with matching size of GoInt.
*/
typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1];

typedef struct { const char *p; GoInt n; } GoString;
typedef void *GoMap;
typedef void *GoChan;
typedef struct { void *t; void *v; } GoInterface;
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;

#endif

/* End of boilerplate cgo prologue.  */

#ifdef __cplusplus
extern "C" {
#endif

extern GoUint64 Add(GoUint64 p0, GoUint64 p1);

#ifdef __cplusplus
}
#endif

但是这个命令

gcc -o test _main.c libgolang.a -lpthread

输出:

libgolang.a(go.o):(.data+0x2150): undefined reference to `NtWaitForSingleObject'
libgolang.a(go.o):(.data+0x21b8): undefined reference to `WSAGetOverlappedResult'
libgolang.a(go.o):(.data+0x21d8): undefined reference to `timeBeginPeriod'
collect2.exe: error: ld returned 1 exit status

go version go1.7rc3 windows/amd64
我想从C代码使用此libgolang.a构建C可执行文件:test.exe
有什么变通办法吗?
一些有用的链接:
http://blog.ralch.com/tutorial/golang-sharing-libraries/
Using Go code in an existing C project
Using Go on existing C project

kpbwa7wx

kpbwa7wx1#

最后至少找到了一个办法:
使用此文件main.go

package main

import "C"
import "fmt"

//export Add
func Add(a, b uint64) uint64 {
    return a + b
}

func main() {
    fmt.Println("Hi")
}

运行以下命令:

go build -buildmode c-archive -o libgolang.a

为了生成libgolang.alibgolang.h,然后使用_main.c

#include <stdio.h>
#include <stdint.h>
#include "libgolang.h"

int main()
{
    uint64_t a=10;
    uint64_t b=20;
    uint64_t c=Add(a,b);
    printf("%ld\n",c);
    return 0;
}

这就是答案(这对我很有效):

gcc -o test _main.c libgolang.a -lWinMM -lntdll -lWS2_32

test.exe创建的文件。
运行:

test.exe

输出:

30
8hhllhi2

8hhllhi22#

微软的Windows总是欺骗我们!
但对于生产代码,我的建议是使用下面的优化编译命令:

go build -ldflags "-s -w" -buildmode c-archive -o libgolang.a

参数**-ldflags“-s -w”将减小最终文件大小。
“libgolang. a”从
4.295.562缩小到1.994.554**。
并且“test.exe”从3.430.485缩小到1.715.561
我猜这是一种渴望的行为!

相关问题