2015-07-28 2 views
2

Я пытаюсь выяснить, как использовать функции WinAPI из Pascal Script/Inno Setup. Я не нашел много примеров кода, как это сделать, и я не программист Pascal. Вот что я сделал до сих пор:Как использовать PathCombine() из WinAPI в Pascal Script/Inno Setup?

Импорт функции

function PathCombine (
    pszPathOut : PChar; 
    pszPathIn : PChar; 
    pszMore : PChar 
) : PChar; 
    external '[email protected] stdcall'; 

и использовать его как это:

function InitializeSetup(): Boolean; 
var 
    a, b,c : PChar; 
    s : string; 
begin 
    SetLength(s, 256); { soon it gets working I'll switch to use MAX_PATH instead of } 
    a := 'C:'; 
    b := 'one\two'; 
    c := PathCombine(s, a, b); 
    MsgBox(s, mbInformation, MB_OK); 
end; 

Выход заключается в следующем:

enter image description here

Ожидаемый результат является:

C: \ один \ два

Я довольно уверен, что я доступ к значениям мусора в памяти, но я не знаю, почему, как это исправить?

ответ

2

Вы не указали, используете ли вы программу Ansi или Unicode Inno Setup.

Но это должно работать в любой версии:

function PathCombine(
    pszPathOut : PAnsiChar; 
    pszPathIn : PAnsiChar; 
    pszMore : PAnsiChar 
) : PAnsiChar; external '[email protected] stdcall'; 

function InitializeSetup(): Boolean; 
var 
    a, b, c: AnsiString; 
begin 
    SetLength(c, 256); { soon it gets working I'll switch to use MAX_PATH instead of } 
    a := 'C:'; 
    b := 'one\two'; 
    PathCombine(c, a, b); 
    MsgBox(c, mbInformation, MB_OK); 
    Result := True; 
end; 

Хотя я настоятельно рекомендую вам использовать Unicode version of Inno Setup и PathCombineW вместо этого.

function PathCombine(
    pszPathOut : string; 
    pszPathIn : string; 
    pszMore : string 
) : Cardinal; external '[email protected] stdcall'; 

function InitializeSetup(): Boolean; 
var 
    a, b, c: string; 
begin 
    SetLength(c, 256); { soon it gets working I'll switch to use MAX_PATH instead of } 
    a := 'C:'; 
    b := 'one\two'; 
    PathCombine(c, a, b); 
    MsgBox(c, mbInformation, MB_OK); 
    Result := True; 
end; 

Обратите внимание, что Inno Setup не хватает PWideChar. Хотя он может маршал string до LPTSTR (PWideChar) аргументы функции, он не может маршал LPTSTR возвращаемое значение. Поэтому я использовал Cardinal для типа возврата. Он имеет тот же размер, что и указатель (для char), поэтому стек будет соответствовать. И нам действительно не нужно возвращаемое значение.

+0

Но для 'PathCombineW' у вас нет' PWideChar' ... – TLama

+0

@TLama Я знаю об этом. Но поскольку нам действительно не нужно возвращаемое значение, вы можете взломать его с помощью функции PathCombine (pszPathOut: string; pszPathIn: string; pszMore: string): PAnsiChar; external'[email protected] stdcall '; 'Правильно? –

+0

Да, это может работать. Хотя я бы предпочел подделать возвращенный указатель, например. как «кардинал», чтобы не допустить его привязку к строке. – TLama

-1

я думаю (хотя я не работал с Pascal/Delphi на некоторое время), что проблема заключается в том, что C "струна" (char *) является индекса на основе, в то время как Паскаль строки индекс на основе (байт используется для хранения длины).

Итак, если вы объявить s переменную как:

s: array[0..255] of Char; //Don't forget to change it to MAX_PATH afterwards 

он должен работать. Кроме того, используйте функцию PathCombine так:

PathCombine(s, a, b); 

Там нет необходимости назначить свой результат (который так же, как s) другой переменной (что вы не собираетесь использовать в любом случае).

+0

Благодарим за голосование.Не могли бы вы также объяснить причину? – CristiFati

+0

Паскаль Скрипт может изначально вывести 'string' на' PChar'. Поэтому базовый индекс не является основной проблемой. (Хотя, конечно, ваш альтернативный код верен.) –

+0

Так что-то неправильно, что я сказал? Выполняется ли преобразование без явного приведения? – CristiFati

 Смежные вопросы

  • Нет связанных вопросов^_^