c - 如何在 Mingw 中将 C 程序编译为 dll 以与 Inno 设置和回调一起使用

标签 c callback mingw inno-setup dllexport

我有以下程序,它是在很多帮助下编写的。它将分解 PKWare DCL 压缩的 .vol 存档(文件 ID RESLIST)并将文件提取到指定的输出文件夹,为提取的文件提供原始 .vol 文件的修改日期。它旨在用于 Inno Setup 安装程序,我想看看是否可以将其编译为 .dll 库,我可以在我的 .iss 脚本中导入,即:

function VolEx( filename, outputpath: String ): Integer; external 'VolExA@volex.dll stdcall';

我通读了http://www.mingw.org/wiki/sampleDLL但很难理解所有 ifdef 和 extern "C"的东西。

此外,我希望它能够更改安装程序中的 WizardForm.FilenameLabel.Caption 以匹配当前正在提取的文件(我知道这需要 InnoTools InnoCallback http://www.sherlocksoftware.org/page.php?id=54 ;使用 FreeArc http://freearc.org/InnoSetup.aspx 完成类似的操作) )

Volex.c(包括来自此处的blast.c和blast.h:https://github.com/madler/zlib/tree/master/contrib/blast)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <sys/stat.h>
#include <time.h>
#include <utime.h>
#include "blast.h"

#define local static
#define VOLID "RESLIST"

struct inbuf {
    unsigned long left;
    unsigned char *buf;
    unsigned size;
    FILE *in;
};

struct stat statbuf;
time_t mtime;
time_t voltime;
struct utimbuf new_times;

local unsigned inf(void *how, unsigned char **buf)
{
    unsigned len;
    struct inbuf *inb = how;

    len = inb->size > inb->left ? inb->left : inb->size;
    len = fread(inb->buf, 1, len, inb->in);
    inb->left -= len;
    *buf = inb->buf;
    return len;
}

local int outf(void *how, unsigned char *buf, unsigned len)
{
    return fwrite(buf, 1, len, (FILE *)how) != len;
}

#define BUFSIZE 16384   /* must fit in unsigned */

local int extract(char *name, unsigned long len, FILE *in, char *path, time_t prevtime)
{
    int err;
    FILE *out;
    struct inbuf inb;
    unsigned char buf[BUFSIZE];

    inb.left = len;
    inb.buf = buf;
    inb.size = BUFSIZE;
    inb.in = in;
    mkdir(path);
    char outPath[strlen(path) + 20];
    strcpy(outPath, path);
    strcat(outPath, "\\");
    strcat(outPath, name);
    out = fopen(outPath, "wb");
    if (out == NULL)
        return 2;
    err = blast(inf, &inb, outf, out);
    fclose(out);
    if (stat(outPath, &statbuf) < 0) {
        perror(outPath);
        return 1;
    }
    mtime = statbuf.st_mtime; /* seconds since the epoch */

    new_times.actime = statbuf.st_atime; /* keep atime unchanged */
    new_times.modtime = prevtime;    /* set mtime to current time */
    if (utime(outPath, &new_times) < 0) {
        perror(outPath);
        return 1;
    }
    return err;
}

int main(int argc, char *argv[])
{
    if ( argc != 3 )
    {
        printf( "Usage: %s <vol> <output path>", argv[0] );
        return 1;
    }
    else
    {
        FILE *in = fopen(argv[1],"rb");
        unsigned long off, next;
        int err;
        unsigned char head[24];

        if (stat(argv[1], &statbuf) < 0) {
            perror(argv[1]);
            return 1;
        }
        voltime = statbuf.st_mtime; /* seconds since the epoch */

        if (fread(head, 1, 8, in) != 8 || memcmp(head, VOLID, 8)) {
            fprintf(stderr, "not the expected .vol format\n");
            return 1;
        }
        off = 8;
        while ((next = fread(head, 1, 24, in)) == 24) {
            off += 24;
            next = head[20] + (head[21] << 8) + ((unsigned long)(head[22]) << 16) +
               ((unsigned long)(head[23]) << 24);

            head[20] = 0;
            err = extract((char *)head, next - off, in, argv[2], voltime);
            if (err) {
                fprintf(stderr, "extraction error %d on %s\n", err, head);
                return 1;
            }
            off = next;
        }
        if (next)
            fprintf(stderr, "%lu bytes ignored at the end\n", next);
        return 0;
    }
}

最佳答案

假设您使用的是 ANSI Inno Setup,则以下 Inno 签名:

function VolEx( filename, outputpath: String ): Integer; external 'VolExA@volex.dll stdcall';

您的 DLL 代码中需要以下 C 签名:

int __stdcall __declspec(dllexport) VolExA(const char *filename, const char *outputpath);

(如果您将 DLL 编译为 C++ 而不是 C,那么您还需要在开头添加 extern "C"。)

您需要在 DLL 中声明此函数,并将适当的代码从上面的“main”移动到其中,然后删除 main 函数并编译为 DLL 而不是控制台应用程序。

先让这部分工作,然后再担心回调的反馈 - 如果您遇到问题,请为此提交一个单独的问题。

关于c - 如何在 Mingw 中将 C 程序编译为 dll 以与 Inno 设置和回调一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18521921/

相关文章:

c - 浮点文字 “.1” 与 C 中的 “0.1” 相同吗?

c - 联锁操作和与 _aligned_malloc 对齐

没有回调的sqlite3_exec

javascript - 如何在自己的回调函数中使用函数的返回值?

c++ - linux下使用mingw交叉编译器声明 'parameters'中的两种或多种数据类型

c++ - mingw32-make 使用 g++ 而不是 cc 或 gcc 来编译 .c 源文件

c - Bron-Kerbosch C 实现

c - 获取Edge浏览器设置窗口的句柄

c++ - 通用 std::function 成员

java - 如何修复JNI项目无法运行的问题