如何将字符串从dll返回到inno脚本 [英] How do I return a string from dll to inno script
问题描述
我在DLL中定义了两个C函数,它们定义在定义文件中,并导出为在Inno设置中使用
I have two C functions in a DLL which are defined in the definition file and are exported for using in Inno setup
char* __stdcall GetName()
{
return "Kishore";
}
void __stdcall getName(char* strName)
{
strcpy(strName, "Kishore");
}
Inno Setup代码将加载自定义dll并调用函数/过程返回名称
The Inno Setup code will load the custom dll and call the function/procedure to return the names
// Inno Setup script
[code]
procedure getName(MacAddress: String);
external 'getName@files:MyDll.dll stdcall setuponly';
function GetName():PAnsiChar;
external 'GetName@files:MyDll.dll stdcall setuponly';
function NextButtonClick(CurPage: Integer): Boolean;
var
StrName: String;
begin
SetLength(StrName,15);
getName(StrName);// displaying only single character
StrName := GetName(); // this call is crashing
end
如何在Inno安装脚本中检索名称没有它崩溃?
How can I retrieve the name in Inno setup script without it crashing?
推荐答案
GetName
应该返回一个 const char *
,不过写的不错。但是请注意,如上所示,返回一个像这样的字符串只能用于文字字符串常量。您不能使用此模式返回计算的字符串值(如果您尝试,它可能会崩溃或给出损坏的数据);因此 getName
是错误的。
GetName
should return a const char *
, however it is otherwise fine as written. Note however that returning a string like this can only ever possibly work for literal string constants, as shown above. You cannot use this pattern to return a calculated string value (if you try that, it will likely crash or give corrupted data); thus getName
is wrong.
另请注意,虽然C区分大小写,但Pascal不是,所以 getName
和 GetName
在Inno脚本中是相同的功能。在上述情况下,您可能会逃避这个问题,因为这些参数是不同的,但是我不会依赖这些参数 - 你应该给他们不同的名字。 (不要在C侧使用相同的名称,因为DLL导出有时也会被无意识地查找。)
Also note that while C is case sensitive, Pascal is not, so getName
and GetName
are the same function in the Inno script. You might be getting away with this in the above case because the parameters are different, but I wouldn't rely on that -- you should give them distinct names. (Don't use the same name on the C side either, as DLL exports are sometimes looked up case-insensitively too.)
要返回一个计算的字符串,应该使用这样的模式:
To return a calculated string, you should use a pattern like this:
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 'CalculateName@files:my.dll stdcall';
...
Max := 16;
Buffer := StringOfChar(#0, Max);
CalculateName(Buffer, Max);
SetLength(Buffer, Pos(#0, Buffer) - 1);
...
存在一些可接受的变体,例如可以使DLL功能返回实际写入缓冲区的字符数,并在随后的SetLength中使用,而不是调用Pos来找到空终止符。
A few acceptable variations exist, for example you can make the DLL function return the number of characters actually written to the buffer, and use that in the subsequent SetLength rather than calling Pos to find the null terminator.
但是您必须:
- 确保双方使用相同的字符串类型,无论是ANSI还是两个Unicode。
- ANSI Inno安装程序仅支持带有
String
类型的ANSI字符串。 - Unicode Inno安装程序支持具有
AnsiString
的ANSI字符串或String
的Unicode字符串。
- Ensure that both sides are using the same string types, either both ANSI or both Unicode.
- ANSI Inno Setup supports only ANSI strings with its
String
type. - Unicode Inno Setup supports either ANSI strings with
AnsiString
or Unicode strings withString
.
在此播放的其中一个约束一方分配的内存必须由同一方释放。您不能安全地释放分配给DLL边界错误一侧的内存。
One of the constraints in play here is that memory allocated by one side must be freed by the same side. You cannot safely release memory allocated on the "wrong" side of the DLL boundary, in either direction.
这篇关于如何将字符串从dll返回到inno脚本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
- ANSI Inno Setup supports only ANSI strings with its
- ANSI Inno安装程序仅支持带有