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中做一个完整的版本:它再次有效
这会给任何人任何其他想法吗?
解决方法
问题与任何字符串的Unicode /非unicodeness无关,但实际上是由于PORT参数中的类型不匹配.
我传递的是ReverseBytes(Port)的结果 – 该参数需要一个uint16_t,即一个Word值.然而,我的Port属性被宣布为(懒惰)为整数!
一旦我修复了这个并将Port声明为Word,它现在适用于D2007和D2009版本的Delphi.
很奇怪.
我只能认为,当引入Unicode支持时,编译器的某些其他边缘情况行为可能以某种方式影响了这一点.