创建目录 zipdll

代码:
unzip.go

package main

/*
#include <stdlib.h>

// 定义回调类型
typedef void (*Callback)(const char*);
// 将 call_callback 声明为 static
static void call_callback(void (*cb)(const char*), const char* message) {
    if (cb != NULL) {
        cb(message);
    }
}

*/
import "C"
import (
    "fmt"
    "io"
    "os"
    "path/filepath"
    "github.com/bodgit/sevenzip"
)

// 计算 7z 文件的总大小
func calculate7zTotalSize(reader *sevenzip.Reader) int64 {
    var totalSize int64
    for _, file := range reader.File {
        totalSize += int64(file.UncompressedSize)
    }
    return totalSize
}

// 解压 7z 文件并调用回调
//export Unzip7zWithCallback
func Unzip7zWithCallback(archivePath *C.char, destDir *C.char, cb C.Callback) {
    goArchivePath := C.GoString(archivePath)
    goDestDir := C.GoString(destDir)

    // 打开 7z 文件
    file, err := os.Open(goArchivePath)
    if err != nil {
        C.call_callback(cb, C.CString("Failed to open 7z file"))
        return
    }
    defer file.Close()

    // 获取文件信息
    fileInfo, err := file.Stat()
    if err != nil {
        C.call_callback(cb, C.CString("Failed to get file info"))
        return
    }

    // 创建 7z 读取器
    reader, err := sevenzip.NewReader(file, fileInfo.Size())
    if err != nil {
        C.call_callback(cb, C.CString("Failed to create 7z reader"))
        return
    }

    // 计算总大小以跟踪进度
    totalSize := calculate7zTotalSize(reader)
    if totalSize == 0 {
        C.call_callback(cb, C.CString("Empty 7z file"))
        return
    }

    var processedSize int64
    progressStep := totalSize / 200 // 0.5% 对应的字节数
    nextProgressTrigger := progressStep

    // 解压文件
    for _, file := range reader.File {
        path := filepath.Join(goDestDir, file.Name)

        // 检查是否是目录
        if file.FileHeader.FileInfo().IsDir() {
            os.MkdirAll(path, 0755)
            continue
        }

        // 创建解压目标文件
        if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
            C.call_callback(cb, C.CString(fmt.Sprintf("Failed to create directory: %s", err.Error())))
            return
        }

        destFile, err := os.Create(path)
        if err != nil {
            C.call_callback(cb, C.CString(fmt.Sprintf("Failed to create file: %s", err.Error())))
            return
        }
        defer destFile.Close()

        // 打开 7z 内部文件
        rc, err := file.Open()
        if err != nil {
            C.call_callback(cb, C.CString(fmt.Sprintf("Failed to open entry in 7z: %s", err.Error())))
            return
        }
        defer rc.Close()

        // 复制文件并更新进度
        buffer := make([]byte, 1024*64) // 每次读取 64KB
        for {
            n, err := rc.Read(buffer)
            if err != nil && err != io.EOF {
                C.call_callback(cb, C.CString(fmt.Sprintf("Failed to read file: %s", err.Error())))
                return
            }
            if n == 0 {
                break
            }

            if _, err := destFile.Write(buffer[:n]); err != nil {
                C.call_callback(cb, C.CString(fmt.Sprintf("Failed to write file: %s", err.Error())))
                return
            }

            // 更新处理的字节数
            processedSize += int64(n)

            // 每 0.5% 调用一次回调
            if processedSize >= nextProgressTrigger {
                progress := float64(processedSize) / float64(totalSize) * 100
                C.call_callback(cb, C.CString(fmt.Sprintf("Progress: %.2f%%", progress)))
                nextProgressTrigger += progressStep
            }
        }
    }

    C.call_callback(cb, C.CString("7z extraction completed successfully"))
}

func main() {}

目录下执行 go mod init
go mod tidy

编译:GOOS=windows GOARCH=amd64 go build -o unzip7z_64.dll -buildmode=c-shared unzip.go
GOOS=windows GOARCH=386 go build -o unzip7z_32.dll -buildmode=c-shared unzip.go