Futurebasic/FBtoC
FBtoC 是 FB 编译器 (FB Compiler.app) 的替代品。将代码翻译成 C 允许 Apple 的开发工具创建通用二进制文件。下面的图表说明了这个过程
FB 编译器 | FB 源代码 → 遗留应用程序(仅限 PPC,CFM 格式,资源分支...) |
---|---|
FBtoC | FB 源代码 → C 源代码 → 带有 Carbon 通用二进制文件的 OS X 应用程序包,以 Mach-O 格式 |
FBtoC 翻译外观项目和独立文件,以及控制台类型的纯文本独立文件。PG 项目无法翻译。使用 FBtoC 通常不需要详细了解 C。
- 编译器 (gcc) 对速度的优化比 FB 编译器更强大。
- 原生 Intel 代码在 Rosetta 下的运行速度比 PPC 代码快 ≈3 倍(或更多)。
- 框架访问比 FB 中更容易(见后)。
- FBtoC 可以自动将指定的文件夹复制到应用程序的资源中(见后)。
- Apple 的现代开发工具适用于 FBtoC 生成的应用程序。工具包括 Xcode 调试器和性能分析器 Shark。
- 应用程序可以构建得尽可能小,只有 64 KB。
- (窗口 1 : 打印 "Hello, world!" : 执行 处理事件 : 直到 gFBQuit)
- 在 Intel Mac 上,崩溃报告是可以解释的,不像遗留的 FB 应用程序那样。
- 与 FB 不同,局部函数变量没有 32k 的限制。
- 还有令人垂涎的通用二进制文件状态!
本节介绍 FutureBASIC 和 FBtoC 的安装。在继续之前,您需要获取以下内容
- 来自:FBtoC 项目页面 的 FBtoC 安装文件和文档
- Apple 开发工具,可在您的 OS C 安装 DVD 或从 Apple 开发者连接网站 获取
FBtoC 应该可以在 OS X 10.3.9 及更高版本上运行。大部分开发和测试是在 OS X 10.4 和 10.5 上完成的。在使用 FBtoC 之前,您应该已经安装了 Apple 的免费开发工具(也称为 Xcode 工具),这些工具来自您的 OS X 安装 CD 或 DVD。
要创建通用二进制文件,您必须拥有 OS X 10.4 或更高版本、gcc 4.0 或更高版本,并安装交叉开发 SDK。如果没有 /Developer/SDKs/MacOSX10.4u.sdk,则只能构建 Mac 本机的体系结构。安装后,Developer 文件夹的 Finder 视图(下面)将显示 SDK。交叉开发是 Xcode 工具安装(来自 OS X DVD 或 CD)的可选部分。
另请参阅 Apple 的文档:Apple 开发工具文档
只需拖放。包含 FBtoC.app 的文件夹还必须包含三个特殊文件夹:build_goodies、Headers 和 User Libraries。
build-goodies 文件夹包含运行时的预翻译部分。更改任何这些文件可能会破坏 FBtoC。
Headers 文件夹包含标准 FB 头文件的一部分。大多数文件都需要修改才能在 FBtoC 中使用。一般来说,现有的 FB 头文件如果简单地复制到此文件夹中,将无法使用。
User Libraries 与 FB 中的功能相同,只是 FBtoC 会忽略鲜为人知的特殊文件 UserFloatPrefs。
FBtoC 中必须以不同的方式完成的一些事情
编译长 if | 用 #if.... 替换 |
enterproc | 标签必须与 enterproc 函数名匹配 |
autoXREFCurr& | 不同的语法;见后 |
DynamicRemoveItems | 不同的语法;见后 |
ControlButtonContentInfo | 用 '.u' 的不同语法;见后 |
HMHelpContent | 用 '.u' 的不同语法;见后 |
Hndl | 用 Handle 替换 |
proc | 不同的语法;此外,标签 *必须* 在 proc 出现的行之前 |
100#, 100! | FBII 格式;都重写为 100.0 |
由于 FBtoC 的操作限制和其他更明显的限制(例如,Intel 不支持 PowerPC 汇编器 - 当然),一些遗留语法无法实现。但是,通常存在用于实现类似目标的现代等效项。将遗留源代码更新为现代等效项可以利用更新的功能,并有助于保持源代码的长期可用性。
beginassem ... endassem | FB 汇编器与 gcc 不兼容(即使在 PPC 上也不兼容) |
tbalias | 稍后讨论 |
dim record | FBII 伪记录;使用真实记录 |
dim as int x;0, hi as byte, lo as byte | 别名变量会导致字节序错误 |
myLong&[0] | 会导致字节序错误 |
appleeventmessage$
def SomeAreButSomeAreNotAvailable
DynamicInsertItems
event&
event%
flushevents // 相反,使用 Toolbox:调用 FlushEvents( _everyEvent, 0 )
folder
get field
on appleevent
on break
on edit
on expr
on finderinfo
on lprint
on overflows
on stop
覆盖本地函数 SomeFunction,覆盖运行时 SomeRuntimeThing(但支持覆盖 _someConst = 1)
parentID
图片字段
syserror
计时器 [函数]
FB 中的 TBalias 语句允许保留旧的工具箱名称,并在 Apple 引入新函数时应用于新函数。这个想法应该是为了节省程序员更新函数名称的一两分钟时间,否则每隔几年就需要进行这项令人厌烦的任务。TBalias 功能现在被认为是有害的,FBtoC 将不支持它。您可能已经升级了您的项目,以便使用正确的(Apple 的官方)工具箱名称。如果没有,请做好准备,FBtoC 会显示错误消息,表明名称有问题。
•• Unknown statement in line 6 of untitled 6: RmveResource( resH ) ^
简单、推荐的且唯一的解决方法是在代码中用 RemoveResource 替换每个出现的 RmveResource。
下面列出了一些在旧 FB 代码中经常被别名的工具箱函数。
FB、FBtoC 和 C | 仅限 FB 的别名 |
---|---|
GetIntlResource | IUGetIntl |
MemError | MemErr |
DisposeHandle | DisposHandle |
DisposePtr | DisposPtr |
AppendResMenu | AddResMenu |
GetMenuHandle | GetMHandle |
CountMenuItems | CountMItems |
EnableMenuItem | EnableItem |
DisableMenuItem | DisableItem |
GetControlValue | GetCtlValue |
GetControlReference | GetCRefcon |
PBReadSync | PBRead |
PBCatMoveSync | CatMove |
PBHCreateSync | HCreate |
PBFlushVolSync | FlushVol |
AEPutParamDesc | AEPutKeyDesc |
SecondsToDate | Secs2Date |
LongSecondsToDate | LongSecs2Date |
RemoveResource | RmveResource |
include "Util_Dialogtests.incl" •• Include file not found in line 1 of OopsMissingFunction.main 1: include "Util_Dialogtests.incl" ^
FBtoC 的 Headers 文件夹中还没有此文件。
include "Util_Files.incl" dim as FSSpec fs dim as Boolean found found = usr FSFileExists( fs ) •• Unknown function in line 4 of OopsMissingFunction.main: FSFileExists 4: found = usr FSFileExists( fs ) ^
Util_Files.incl 存在于 FBtoC 的 Headers 文件夹中;错误出现是因为函数 usr FSFileExists 被某个小气的官员给有条件地移除了,希望只是暂时性的。[稍后添加的说明:现在实现了 FSFileExists]
在 FBtoC 运行时中保存的旧 FB 代码
CLEAR LOCAL dim pBlk.128 LOCAL FN FBGetFolderName(DirID&,WDRefNum%,@StrPtr&) StrPtr&.Nil$ = "" pBlk.ioDirID& = DirID& pBlk.ioVRefNum% = WDRefNum% pBlk.ioNamePtr& = StrPtr& pBlk.ioFDirIndex%= -1 long if FN PBGetCatInfoSync(@pBlk) StrPtr&.Nil$ = "Error" end if END FN
long FBGetFolderName( long DirID, short WDRefNum, long StrPtr ) { char pBlk[128] = {}; PLstrcpy( ((StringPtr)StrPtr), "\p" ); *(long*)(pBlk + 48) = DirID; *(short*)(pBlk + 22) = WDRefNum; *(long*)(pBlk + 18) = StrPtr; *(short*)(pBlk + 28) = -1; if ( PBGetCatInfoSync( (void*)&pBlk ) ) { PLstrcpy( ((StringPtr)StrPtr), "\pError" ); } // 'end if' return 0; }
FBtoC 的众多内部函数之一
local fn DefinePointRecord dim as VarInfo varInfo BlockZero( varInfo, sizeof( varInfo ) ) varInfo.varType = _shortVarType // for fields fn SuppressTypedefs fn StartRecordDefinition( "Point" ) fn AddFieldToRecordDefinition( "v", "", varInfo ) fn AddFieldToRecordDefinition( "h", "", varInfo ) fn FinishRecordDefinition fn DontSuppressTypedefs end fn
long DefinePointRecord() { VarInfo varInfo; BlockZero( &varInfo, sizeof( varInfo ) ); varInfo.varType = 3; SuppressTypedefs(); StartRecordDefinition( PLstrcpy( gFBStrStk[++gFBStk], "\pPoint" ) ); AddFieldToRecordDefinition( PLstrcpy( gFBStrStk[++gFBStk], "\pv" ), PLstrcpy( gFBStrStk[++gFBStk], "\p" ), &varInfo ); AddFieldToRecordDefinition( PLstrcpy( gFBStrStk[++gFBStk], "\ph" ), PLstrcpy( gFBStrStk[++gFBStk], "\p" ), &varInfo ); FinishRecordDefinition(); DontSuppressTypedefs(); return 0; }