Вопрос по c, decompression, callback, dll, inno-setup – Использование обратного вызова для отображения имен файлов из внешней библиотеки декомпрессии (Inno Setup)

1

Первоначально спросилВот, но попросили представить его как отдельный вопрос.

У меня есть ниже dll, закодированный в C ниже, что яиспользуя Inno Setup Installer для извлечения файлов игры. Это замещающий установщик для игры, в которой изначально использовался 16-разрядный установщик, а файлы копируются с компакт-диска. Я'я хотел бы иметь возможность использоватьInnoTools InnoCallback для отображения имен файлов, извлеченных с использованием моей библиотеки DLL, но, поскольку это мое первое занятие по программированию на C, я понятия не имею, как это сделать. Пример этой функции можно найти здесь:http://freearc.org/InnoSetup.aspx

Я хотел бы иметь возможность установить WizardForm.FilenameLabel.Caption, используя имя файла из моей внешней библиотеки DLL.

Соответствующие разделы моего скрипта Inno Setup:

function VolEx( filename, outputpath: String ): Integer; external '[email protected]:volex.dll stdcall';

(DriveLetter - это путь к CD-ROM, т.е.D: \» поэтому вывод в настоящее время читает "D: \ \ archive.vol мира», Выход яЯ стремлюсь к "C: \ игровой путь \ Мир \ архив \ file.ext ")

procedure VolExtract();
begin
  if not DirExists(WizardDirValue() + '\' + Worlds[w]) then
  begin
    CreateDir(WizardDirValue() + '\' + Worlds[w]);
  end;
  for n := 0 to 3 do begin
    WizardForm.FilenameLabel.Caption := DriveLetter + Worlds[w] + '\' + Reslists[n] + '.vol';

    if VolEx(DriveLetter + Worlds[w] + '\' + Reslists[n] + '.vol', WizardDirValue() + '\' + Worlds[w] + '\' + Reslists[n])  0 then
    begin
      // Handle Fail
      MsgBox(CustomMessage('FileErr'), mbInformation, MB_OK);
      WizardForm.Close;
    end;

VolEx.c (включает в себя blast.c и blast.h отсюда:https://github.com/madler/zlib/tree/master/contrib/blast)

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#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, const 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 __stdcall __declspec(dllexport) VolEx(const char *filename, const char *outputpath)
{
    FILE *in = fopen(filename,"rb");
    unsigned long off, next;
    int err;
    unsigned char head[24];

    if (stat(filename, &statbuf) < 0) {
        perror(filename);
        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, outputpath, 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;
}
Мой вопрос заключается в том, что мне нужно изменить в моей dll для связи с dll InnoTools Callback и, в свою очередь, обновить метку WizardForm.FilenameLabel.Caption в сценарии. У меня нетЯ не смог найти никакой информации о том, как это сделать, кроме этого скрипта FreeArc. user477276
Извините, но я нене получить этот пост. Это'Это почти так же, как ваш предыдущий, где я тоже потерялся. Какой у вас вопрос здесь? Хотите показать, как обернуть определенный колбэк? Если так, то каков его прототип? TLama
Inno Setup показывает текущий файлРаспаковывая на WizardForm.FilenameLabel.Caption, у меня есть дополнительные файлы, которые я должен извлечь из нестандартных архивов на CD-ROM, используя volex.dll. В моем скрипте Inno Setup у меня есть параметр AfterInstall для запуска VolExtract () и вызова volex.dll для извлечения этих дополнительных файлов. Я хочу иметь возможность обновить WizardForm.FilenameLabel.Caption с именами файлов, когда они извлекаются с помощью volex.dll и это 'Насколько я понимаю, мне нужно использовать этот DLL InnoTools Callback для этого. user477276

Ваш Ответ

1   ответ
2

InnoTools Callback.

Это'это довольно просто, вы просто объявляете процедуру, подобную этой (опять же, если выповторное использование ANSI Inno - некоторые типы должны быть изменены для версии Unicode):

[Code]
type
    TMyCallback = procedure(Filename: PChar);

function WrapMyCallback(Callback: TMyCallback; ParamCount: Integer): LongWord;
    external '[email protected]:innocallback.dll stdcall';

procedure DoSomethingInTheDll(Blah: Integer; Foo: String; ...; Callback: LongWord);
    external '[email protected]:mydll.dll stdcall';

procedure MyCallback(Filename: PChar);
begin
    // do whatever, eg. update the filename label
end;

// wherever you're about to call your DLL
var Callback : LongWord;
// ...
    Callback := WrapMyCallback(@MyCallback, 1); // 1 parameter
    // pass the callback to your DLL either via a dedicated function
    // or as a parameter of your existing function
    DoSomethingInTheDll(blah, foo, ..., Callback);

На стороне DLL:

typedef void (__stdcall *MyCallback)(const char *filename);

Затем вы можете объявить переменные типаMyCallback в параметрах функций, а затем вызывать их, как если бы они были родными функциями C, и он будет запускать код внутри сценария Inno.

void __stdcall __declspec(dllexport)
    DoSomethingInTheDll(int blah, const char *foo, ..., MyCallback callback)
{
    // ...
    callback(foo);
}
Нужно было изменить некоторые вещи в моей C-программе, чтобы она не давала мне ошибок, но теперь это работает, спасибо! user477276

Похожие вопросы