GetName
должен вернуть const char *
, однако в остальном это прекрасно. Обратите внимание, однако, что возвращение такой строки может только когда-либо работать для строковых строковых констант, как показано выше. Вы не можете использовать этот шаблон для возврата вычисленного строкового значения (если вы попробуете это, оно, скорее всего, приведет к краху или даст поврежденные данные); таким образом, getName
является неправильным.
Также обратите внимание, что хотя C чувствителен к регистру, Pascal нет, поэтому getName
и GetName
- это те же функции в скрипте Inno. Вам может избежать этого в приведенном выше случае, потому что параметры разные, но я бы не стал полагаться на это - вы должны дать им разные имена. (Не используйте то же имя на стороне C либо, так как экспорт DLL иногда посмотрел регистронезависимо тоже.)
Чтобы вернуть вычисленную строку, вы должны использовать шаблон, как это:
DLL код:
void __stdcall CalculateName(char *buffer, size_t size)
{
strncpy(buffer, "whatever", size);
buffer[size-1] = 0;
}
Inno код: есть
procedure CalculateName(Buffer: AnsiString; Max: Cardinal);
external '[email protected]:my.dll stdcall';
...
Max := 16;
Buffer := StringOfChar(#0, Max);
CalculateName(Buffer, Max);
SetLength(Buffer, Pos(#0, Buffer) - 1);
...
несколько приемлемых вариантов, например, вы можете сделать функцию DLL возвращать число символов на самом деле написано в буфер и использовать это в последующей SetLength, а не вызывать Pos, чтобы найти нулевой ограничитель.
Но вы должны:
- Убедитесь, что обе стороны используют одни и те же типы строк, либо как ANSI или Unicode как.
- ANSI Inno Setup поддерживает только строки ANSI с его типом
String
.
- Unicode Inno Setup поддерживает либо строки ANSI с
AnsiString
, либо строки Unicode с String
.
- При использовании строк в Юникоде убедитесь, что обе стороны согласны с тем, указано ли значение Max и/или возвращаемое значение в символах или байтах (код примера предполагает, что он находится в символах).
- Перед вызовом функции используйте SetLength или StringOfChar, чтобы убедиться, что размер буфера соответствует требуемой максимально возможной длине результата.
- Убедитесь, что вызываемая функция не пытается записать эту максимальную длину (что проще, если это предусмотрено как параметр функции).
- Убедитесь, что если вы используете Pos, вызываемая функция должна гарантировать, что значение имеет нулевое завершение (или вам нужно быть более осторожным, чем показано в примере).
- Убедитесь, что после вызова вы обрезаете строку до фактической длины либо с помощью возвращаемого значения, либо путем поиска нулевого терминатора.
Одно из ограничений в игре заключается в том, что память, выделенная одной стороной, должна быть освобождена с той же стороны. Вы не можете безопасно освободить память, выделенную на «неправильной» стороне границы DLL, в любом направлении.
Измените прототип функции 'getName', чтобы использовать' AnsiString' вместо 'string', поскольку вы использовали версию Inno Setup Unicode, но тип' char' в вашем коде на C. И не используйте функцию 'GetName', потому что DLL должна будет выделить и освободить память для строки, которая семантически ошибочна. – TLama
Я хочу получить значение из getName и использовать «StrName» для какой-либо цели. Имя отображается в dll, но когда оно возвращается к сценарию inno, значение символа является одиночной цифрой. С вашим sugesstion также он не работал – user3274591
10-15 символов – user3274591