在Delphi 7中工作的ZeroConf / Bonjour代码在2009年不起作用

我有DNSServiceRegister的以下声明:
function DNSServiceRegister
      (
      var sdRef: TDNSServiceRef;
      const flags: TDNSServiceFlags;
      const interfaceIndex: uint32_t;
      const name: PUTF8String;                    //* may be NULL */
      const regType: PUTF8String;
      const domain: PUTF8String;                  //* may be NULL */
      const host: PUTF8String;                    //* may be NULL */
      const port: uint16_t;
      const txtLen: uint16_t;
      const txtRecord: Pointer;                 //* may be NULL */
      const callBack: TDNSServiceRegisterReply; //* may be NULL */
      const context: Pointer                    //* may be NULL */
      ): TDNSServiceErrorType; stdcall; external DNSSD_DLL;

在我的Bonjour框架中,我对已宣布的服务进行了以下响应(即通过Bonjour实际开始宣布自己):

procedure TAnnouncedService.Activate;
  var
    flags: Cardinal;
    name: UTF8String;
    svc: UTF8String;
    pn: PUTF8String;
    ps: PUTF8String;
  begin
    fPreAnnouncedServiceName := ServiceName;

    inherited;

    if AutoRename then
      flags := 0
    else
      flags := kDNSServiceFlagsNoAutoRename;  { - do not auto-rename }

    if (ServiceName <> '') then
    begin
      name  := ServiceName;
      pn    := PUTF8String(name);
    end
    else
      pn := NIL;

    svc := ServiceType;
    ps  := PUTF8String(svc);

    CheckAPIResult(DNSServiceRegister(fHandle,flags,0 { interfaceID - register on all interfaces },pn,ps,NIL { domain - register in all available },NIL { hostname - use default },ReverseBytes(Port),0   { txtLen },NIL { txtRecord },DNSServiceRegisterReply,self));
    TBonjourEventHandler.Create(fHandle);
  end;

这比我认为的严格要求更加冗长,当然它在Delphi 7中的表现非常简洁.我已经将大量操作扩展为明确的步骤以便于调试,例如能够识别可能在Delphi 2009中“引擎盖下”发生的字符串有效负载的任何隐式转换.

即使在这种不整洁的扩展形式中,这段代码在Delphi 7中编译并运行得非常好,但如果我编译并运行Delphi 2009,我就不会得到我的服务声明.

例如,如果我将此代码作为Delphi 7应用程序的一部分运行以注册_daap._tcp服务(iTunes共享库),我会在运行的iTunes实例中看到它弹出.如果我在Delphi 2009中重新编译完全相同的应用程序而不进行修改并运行它,我看不到我的服务出现在iTunes中.

使用dns-sd命令行实用程序进行监视时,我会得到相同的行为.也就是说,用Delphi 7编译的服务代码就像我期望的那样,在Delphi 2009中编译 – 什么都没有.

我没有从Bonjour API中获得任何错误 – 正在使用ErrorCode 0(零)调用DNSServiceRegisterReply回调,即成功,如果我提供了NIL名称参数,并在标志中指定了AutoRename,那么我的服务被分配正确默认名称.但是该服务仍未显示在iTunes中.

我不知道发生了什么.

正如您可能从代码扩展中可以看出的那样,我一直在追逐Delphi 2009中Unicode实现所引入的潜在错误,但这似乎无处可寻.

该代码最初是针对Bonjour API / SDK的1.0.3版开发的.我已经更新到1.0.6,如​​果涉及到某种程度,没有任何成功. afaict 1.0.6只添加了一个新函数来获取“属性”,它目前只支持“DaemonVersion”属性来获得Bonjour版本 – 这是完美的.

注意:我知道现在的代码在技术上并不是Delphi 7中的UTF8安全 – 我已尽可能地消除了显式转换,以便尽可能简化Delphi 2009适用的自动转换.我现在的目标是让它在Delphi 2009中运行,然后从该解决方案向后工作,希望找到适用于早期版本Delphi的兼容方法.

另请注意:我最初也在浏览广告服务时遇到问题,即在网络上识别实际的iTunes共享库.这些问题是由Delphi 2009中的Unicode处理引起的,并且已经解决.我的Delphi 2009代码能够识别实际的iTunes共享库并查询它的TXT记录.只有这项服务注册无效.

我必须错过一些愚蠢而明显的东西.

有没有人有任何想法?!

UPDATE

回到这个问题后,我现在发现了以下内容:

如果我打开了D2009之前和D2009 IDE(例如D2006和D2010),同时将同一个项目加载到两个IDE中:

>在2006年建立并运行:它有效 – 我的服务公告被iTunes收录
>切换到D2010并运行(不构建):它执行最小的编译,运行和工作.
>在D2010中进行全面构建:它停止工作
>切换回D2006并运行(不构建):它不起作用
>在D2006中做一个完整的版本:它再次有效

这会给任何人任何其他想法吗?

解决方法

答案是令人难以置信的.一方面,我做了一个完全愚蠢,非常简单的错误,但另一方面它永远不应该 – 据我所知 – 已经在任何版本的Delphi中工作过!

问题与任何字符串的Unicode /非unicodeness无关,但实际上是由于PORT参数中的类型不匹配.

我传递的是ReverseBytes(Port)的结果 – 该参数需要一个uint16_t,即一个Word值.然而,我的Port属性被宣布为(懒惰)为整数!

一旦我修复了这个并将Port声明为Word,它现在适用于D2007和D2009版本的Delphi.

很奇怪.

我只能认为,当引入Unicode支持时,编译器的某些其他边缘情况行为可能以某种方式影响了这一点.

相关文章

 从网上看到《Delphi API HOOK完全说明》这篇文章,基本上都...
  从网上看到《Delphi API HOOK完全说明》这篇文章,基本上...
ffmpeg 是一套强大的开源的多媒体库 一般都是用 c/c+&#x...
32位CPU所含有的寄存器有:4个数据寄存器(EAX、EBX、ECX和ED...
1 mov dst, src dst是目的操作数,src是源操作数,指令实现的...