使用Golang创建共享DLL的方法与技巧

使用Golang创建共享DLL的方法与技巧 我需要创建一个暴露变量和函数的DLL。 实现此功能的C代码如下:

#include <stdio.h>

double In = 1.0;
double Out = 0.0;
double G = 2;

void step() {
    Out = G * In;
}

编译命令为:gcc -shared -o root.dll example.c

其他系统将基于内存地址获取值。

我想使用Golang实现相同的功能,但 //export 指令没有生成可读的DLL方法。有人能给我一些建议吗?

4 回复

尝试使用 go build -buildmode=c-shared -o example.dll . 命令。

func main() {
    fmt.Println("hello world")
}

更多关于使用Golang创建共享DLL的方法与技巧的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


感谢 MIMO431。

它创建了 DLL,但没有任何导出的方法或变量可用。

请查看以下对比:

image

Golang 只能导出函数。为此,需要使用 CGO、首字母大写的函数以及导出注释,例如:

//export <函数名>
func <函数名>(...){...}

示例代码:

package main

import "C"

// 全局变量
var (
	In  float64 = 1.0
	Out float64 = 0.0
	G   float64 = 2.0
)

//export Step
func Step() {
	Out = G * In
}

//export GetIn
func GetIn() float64 {
	return In
}

//export SetIn
func SetIn(value float64) {
	In = value
}

//export GetOut
func GetOut() float64 {
	return Out
}

//export GetG
func GetG() float64 {
	return G
}

//export SetG
func SetG(value float64) {
	G = value
}

func main() {
	// 这对于共享库中的 main 函数是必需的,但从 C 调用时不会执行
}

这将生成: image

它应该由示例命令生成:

go build -buildmode=c-shared -o example.dll .

在Go中创建共享DLL需要特殊的编译方式和导出标记。以下是实现相同功能的Go代码示例:

package main

import "C"

//export In
var In float64 = 1.0

//export Out
var Out float64 = 0.0

//export G
var G float64 = 2.0

//export step
func step() {
    Out = G * In
}

func main() {
    // 空main函数,仅用于编译
}

编译命令:

go build -buildmode=c-shared -o root.dll example.go

生成的DLL将包含导出的变量和函数。其他系统可以通过以下方式访问:

C语言调用示例:

#include <stdio.h>
#include <windows.h>

typedef double (*get_double_func)();
typedef void (*step_func)();

int main() {
    HINSTANCE hDLL = LoadLibrary("root.dll");
    if (hDLL != NULL) {
        get_double_func getIn = (get_double_func)GetProcAddress(hDLL, "In");
        get_double_func getOut = (get_double_func)GetProcAddress(hDLL, "Out");
        get_double_func getG = (get_double_func)GetProcAddress(hDLL, "G");
        step_func step = (step_func)GetProcAddress(hDLL, "step");
        
        if (getIn && getOut && getG && step) {
            printf("In: %f, Out: %f, G: %f\n", getIn(), getOut(), getG());
            step();
            printf("After step - Out: %f\n", getOut());
        }
        
        FreeLibrary(hDLL);
    }
    return 0;
}

关键注意事项:

  1. 必须使用 //export 注释标记要导出的变量和函数
  2. 编译时必须使用 -buildmode=c-shared 参数
  3. 导出的变量实际上是函数指针,需要通过GetProcAddress获取
  4. 导出的变量在DLL中是只读的,如果需要修改,需要通过导出的setter函数

如果需要修改导出的变量值,可以添加setter函数:

//export setIn
func setIn(value float64) {
    In = value
}

//export setG
func setG(value float64) {
    G = value
}
回到顶部