zoukankan      html  css  js  c++  java
  • Go win32

    上次说到,我们的GO可以执行系统调用,嘿嘿

    不假,但如果你认为你已经掌握了,哈哈,那么不然

    网上的例子,总是不深入,不彻底,除非是官网上的demo,也就是说只有设计者才知道告诉你什么才是它设计的正真意义

    好了,就让windows上的本地dll调用,来说明问题吧

    //构造win32本地库

    //test.h

    #ifndef _TEST_
    # define _TEST_

    # ifdef TEST
    # define Export _declspec(dllexport)
    # else
    # define Export _declspec(dllimport)

    #endif

    Export double add(double da ,double db);
    Export double subtract(double da , double db);
    Export int add_ex(int a, int b, int* result);
    Export int add_ex_ex(double a, double b, double* result);
    Export int add_ex_ex_ex(double* a, double* b, double* result);

    #endif

    //test.c

    #define TEST
    #include "test.h"

    Export double add(double da ,double db)
    {
    return da+db;
    }
    Export double subtract(double da , double db)
    {
    return da-db;
    }

    Export int add_ex(int a, int b, int* result)
    {
    *result = a+b;
    return 1;
    }

    Export int add_ex_ex(double a, double b, double* result)
    {
    printf("input param1:=%lf ", a);
    printf("input param2:=%lf ", b);
    *result = a+b;
    printf("result:=%lf ", *result);
    return 1;
    }

    Export int add_ex_ex_ex(double* a, double* b, double* result)
    {
    printf("input param1:=%lf ", *a);
    printf("input param2:=%lf ", *b);
    *result = *a+*b;
    printf("result:=%lf ", *result);
    return 1;
    }

    //生成库

    cl -c test.c

    link -dll test.obj

    我们会得到test.dll的win32动态链接库

    //go 通过syscall来调用test.dll本地库

    //win32.go

    package main

    import (
    "fmt"
    "syscall"
    "unsafe"
    )

    func main() {

    const f = "%T(%v) "
    test, err := syscall.LoadLibrary("test.dll")
    if (err!=nil) {
    fmt.Println("test.dll not found")
    return
    }
    defer syscall.FreeLibrary(test)
    add, err := syscall.GetProcAddress(syscall.Handle(test), "add")
    if (err!=nil) {
    fmt.Println("add not found")
    return
    }
    add_ex, err := syscall.GetProcAddress(syscall.Handle(test), "add_ex")
    if (err!=nil) {
    fmt.Println("add_ex not found")
    return
    }
    add_ex_ex, err := syscall.GetProcAddress(syscall.Handle(test), "add_ex_ex")
    if (err!=nil) {
    fmt.Println("add_ex_ex not found")
    return
    }
    add_ex_ex_ex, err := syscall.GetProcAddress(syscall.Handle(test), "add_ex_ex_ex")
    if (err!=nil) {
    fmt.Println("add_ex_ex not found")
    return
    }
    fmt.Printf(f, add, add)
    fmt.Printf(f, add_ex, add_ex)
    var a1 float64 = float64(1.0276)
    var a2 float64 = float64(2.7865)
    fmt.Printf(f, a1, a1)
    fmt.Printf(f, a2, a2)
    fmt.Println("a1+a2", a1+a2)

    r, _, retstr := syscall.Syscall(uintptr(add), 2,
    uintptr(a1),
    uintptr(a2),
    0)
    fmt.Println("add ", retstr)
    fmt.Printf(f, r, r)
    add_value := int32(0)
    r, _, retstr = syscall.Syscall(uintptr(add_ex), 3,
    uintptr(1),
    uintptr(2),
    uintptr(unsafe.Pointer(&add_value)))
    fmt.Println("add_ex", retstr)
    fmt.Printf(f, r, r)
    fmt.Printf(f, add_value,add_value)
    add_value_ex := float64(0)
    r, _, retstr = syscall.Syscall(uintptr(add_ex_ex), 3,
    uintptr(a1),
    uintptr(a2),
    uintptr(unsafe.Pointer(&add_value_ex)))
    fmt.Printf(f, uintptr(a1), uintptr(a1))
    fmt.Println("add_ex_ex", retstr)
    fmt.Printf(f, r, r)
    fmt.Printf(f, add_value_ex, add_value_ex)

    r, _, retstr = syscall.Syscall(uintptr(add_ex_ex_ex), 3,
    uintptr(unsafe.Pointer(&a1)),
    uintptr(unsafe.Pointer(&a2)),
    uintptr(unsafe.Pointer(&add_value_ex)))
    fmt.Println("add_ex_ex_ex", retstr)
    fmt.Printf(f, r, r)
    fmt.Printf(f, add_value_ex, add_value_ex)
    }

    //运行

    go build win32.go

    win32.exe

    //结果

    uintptr(140729033560064)
    uintptr(140729033560128)
    float64(1.0276)
    float64(2.7865)
    a1+a2 3.8141000000000003
    add The operation completed successfully.
    uintptr(140729033560064)
    add_ex The operation completed successfully.
    uintptr(1)
    int32(3)
    input param1:=0.000000
    input param2:=0.000000
    result:=0.000000
    uintptr(1)
    add_ex_ex The operation completed successfully.
    uintptr(1)
    float64(1.5e-323)
    input param1:=1.027600
    input param2:=2.786500
    result:=3.814100
    add_ex_ex_ex The operation completed successfully.
    uintptr(1)
    float64(3.8141000000000003)

    Finally:

    我在这里告诉你事实如下,这个很重要。。。。。。

    GO与win32本地交互时,只能给win32接口函数传递uiintptr类型参数

    uintptr在GO里被当作指针来看待,它本身是整形(32/64位),但要命的是网上的例子会拿这个来做数值参数举例子调用系统函数,读者会误以为这是数值参数的模板(int, float, double)

    其实不然,我给你更正:

    1. 接口只能返回uintptr类型(一般用0表示失败,1表示成功)

    2. 无论GO什么类型,往win32本地库接口里传递时都得传递指针进去(网上会有GO取字符串的指针的例子,很实用)

    3. 自己设计的本地库接口得操作相应的指针类型(char*,wchar_t*, int*, float*,double*)

    好了,听我的,你就又活了

    最后,我认为,如果你已经懂了,那么,你的路(Windows+GO)将会一番风顺

    哈哈哈,祝你成功!

  • 相关阅读:
    Deltix Round, Summer 2021
    CF1558F Strange Sort 题解
    将文本复制到粘贴板上
    Mac安装2021ps
    腾讯云TDSQL-C云原生数据库技术
    腾讯云分布式数据库TDSQL再获认可
    T-TDSQL的核心技术
    TDSQL原创技术的出发点
    拓路前行-TDSQL追求极致体验的这一路
    TDSQL多集群下的自动化和交付
  • 原文地址:https://www.cnblogs.com/woodzcl/p/7562629.html
Copyright © 2011-2022 走看看