加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

如何将字符串从DLL返回到Inno Setup Pascal Script

发布时间:2020-12-13 20:26:05 所属栏目:Windows 来源:网络整理
导读:我在DLL中有两个C函数,它们在定义文件中定义并导出以便在Inno Setup中使用. char* __stdcall GetName(){ return "Kishore";}void __stdcall getName(char* strName){ strcpy(strName,"Kishore");} Inno安装代码将加载自定义DLL并调用函数/过程以返回名称 { I
我在DLL中有两个C函数,它们在定义文件中定义并导出以便在Inno Setup中使用.
char* __stdcall GetName()
{
        return "Kishore";
}
void __stdcall getName(char* strName)
{
     strcpy(strName,"Kishore");
}

Inno安装代码将加载自定义DLL并调用函数/过程以返回名称

{ 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安装脚本中检索名称而不会崩溃?

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 'CalculateName@files: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仅支持具有String类型的ANSI字符串.
> Unicode Inno Setup支持带有AnsiString的ANSI字符串或带有String的Unicode字符串.

>使用Unicode字符串时,请确保双方同意是否以字符或字节指定Max和/或返回值(示例代码假定它以字符为单位).
>在调用函数之前,使用SetLength或StringOfChar确保缓冲区的大小已达到所需的最大可能结果长度.
>确保被调用函数不会尝试写入超过此最大长度(如果将其作为函数的参数提供,则更容易).
>确保如果您使用Pos,则被调用函数必须确保该值以空值终止(或者您需要比示例中所示更加小心).
>确保在调用之后将字符串截断为实际长度,方法是使用返回值或查找空终止符.

这里的约束之一是由一侧分配的存储器必须由同一侧释放.您无法在任一方向上安全地释放在DLL边界的“错误”侧分配的内存.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读