zoukankan      html  css  js  c++  java
  • Golang 编译成 DLL 文件

    golang 编译 dll 过程中需要用到 gcc,所以先安装 MinGW。

    windows 64 位系统应下载 MinGW 的 64 位版本: https://sourceforge.net/projects/mingw-w64/

    下载后运行 mingw-w64-install.exe,完成 MingGW 的安装。

    首先撰写 golang 程序 exportgo.go:

    package main
    
    import "C"
    import "fmt"
    
    //export PrintBye
    func PrintBye() {
        fmt.Println("From DLL: Bye!")
    }
    
    //export Sum
    func Sum(a int, b int) int {
        return a + b;
    }
    
    func main() {
        // Need a main function to make CGO compile package as C shared library
    }
    

    编译成 DLL 文件:

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

    编译后得到 exportgo.dll 和 exportgo.h 两个文件。

    参考 exportgo.h 文件中的函数定义,撰写 C# 文件 importgo.cs:

    using System;
    using System.Runtime.InteropServices;
    
    namespace HelloWorld
    {
        class Hello 
        {
            [DllImport("exportgo.dll", EntryPoint="PrintBye")]
            static extern void PrintBye();
    
            [DllImport("exportgo.dll", EntryPoint="Sum")]
            static extern int Sum(int a, int b);
    
            static void Main() 
            {
                Console.WriteLine("Hello World!");
                PrintBye();
    
                Console.WriteLine(Sum(33, 22));
            }
    

    编译 CS 文件得到 exe

    csc importgo.cs
    

    将 exe 和 dll 放在同一目录下,运行。

    >importgo.exe
    
    Hello World!
    From DLL: Bye!
    55
    

    golang 中的 string 参数在 C# 中可以如下引用:

    public struct GoString
        {
            public string Value { get; set; }
            public int Length { get; set; }
    
            public static implicit operator GoString(string s)
            {
                return new GoString() { Value = s, Length = s.Length };
            }
    
            public static implicit operator string(GoString s) => s.Value;
        }
    

      

    // func.go
    package main
    
    import "C"
    import "fmt"
    
    //export Add
    func Add(a C.int, b C.int) C.int {
    	return a + b
    }
    
    //export Print
    func Print(s *C.char) {  
    /* 
    函数参数可以用 string, 但是用*C.char更通用一些。
    由于string的数据结构,是可以被其它go程序调用的,
    但其它语言(如 python)就不行了
    */
    	print("Hello ", C.GoString(s)) //这里不能用fmt包,会报错,调了很久...
    }
    func main() {	
    }                                                                                                                                        
    
     

    编译
    go build -ldflags "-s -w" -buildmode=c-shared -o func.dll func.go
    还是有点大的,880KB,纯C 编译的只有48KB,应该是没有包含全部的依赖吧,go是全包进来了

    Go 调用

    package main
    import (
    	"fmt"
    	"syscall"
    )
    
    func main() {
    	dll := syscall.NewLazyDLL("func.dll")
    	add := dll.NewProc("Add")
    	prt := dll.NewProc("Print")
    	r, err, msg := add.Call(32, 44)
    	fmt.Println(r)
    	fmt.Println(err)
    	fmt.Println(msg)
    	
    	name := C.CString("Andy")
    	prt.Call(uintptr(unsafe.Pointer(name)))
    }
    
    out:
    76
    0
    The operation completed successfully.
    Hello Andy
    

    Python 调用

    from ctypes import CDLL, c_char_p
    dll = CDLL("func.dll")
    dll.Add(32, 33)
    dll.Print(c_char_p(bytes("Andy", "utf8")))
    

    C++调用

    #include <iostream>
    #include <windows.h>
    
    using namespace std;
    typedef int(*pAdd)(int a, int b);
    typedef void(*pPrt)(char* s);
    
    int main(int argc, char *argv[])
    {
        HMODULE dll= LoadLibraryA("func.dll");
        pAdd add = (pAdd)GetProcAddress(dll, "Add");
        pPrt prt = (pPrt)GetProcAddress(dll, "Print");
        cout << add(321, 33) << endl;
        prt("Andy");
        FreeLibrary(dll);
        return 0;
    }
    

      

  • 相关阅读:
    linux basename 和 dirname 获取当前路径
    灵活的装饰器
    ubuntu 20version install wechat
    git pull 总提示让输入merge 信息
    Linux脚本中$#、$0、$1、$@、$*、$$、$?
    ansible
    MMD讲解
    再生希尔伯特空间与核函数讲解
    流形学习
    聚类
  • 原文地址:https://www.cnblogs.com/dfsxh/p/10305072.html
Copyright © 2011-2022 走看看