文章编号:10630时间:2024-09-28人气:
在 C 编程中,小字符串优化是一种技术,它可以显著提升应用程序的性能和效率,特别是对于大量处理小字符串的应用程序。
小字符串通常是指长度在 16 个字节或更短的字符串。
小字符串优化技术主要通过以下方式实现:
strcmp
和
strlen
)可以提高性能,因为这些函数针对小字符串进行了优化。
以下示例展示了如何应用小字符串优化:
// 使用寄存器变量存储小字符串register char str = "Hello";// 使用局部变量存储小字符串void my_function() {char str[] = "World";}// 使用内置字符串函数比较小字符串if (strcmp("
1 提高子菜单速度位 置:HKEY_CURRENT_USER\Control Panel\Desktop键值名:Menushowdelay双击键值Menushowdelay后,弹出该键值的编辑窗口,在文本输入框内输入“0”后,再单击“确定”按钮即可。 注意在系统默认的菜单弹出效果下,不易感觉到菜单弹出速度的提高;这时,请在桌面上单击“属性”命令,弹出“显示 属性”窗口,然后在“效果”标签下将“动画显示菜单和工具提示”下的“淡入淡出效果”改为“滚动效果”。 2 去掉“关闭系统”位 置:HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer键值名:NoClose取 值:1为隐藏、0为显示3 自动刷新窗口内容位 置:HKEY_LOCAL_MACHINE\System\Currentcontrolset\Control\Update键值名:UpdateMode取 值:0、1若“UpdateMode”键值为0,则设置为自动刷新,若“UpdateMode”键值为1,则设置为手工刷新;这等于在资源管理器窗口内按“F5”键或者在“查看”菜单中选择“刷新”命令。 4 去掉“设置”一 位 置:HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer键值名:NoSetFolders取 值:1为隐藏、0为显示二 位 置:HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer键值名:NoSetTaskbar取 值:1为隐藏、0为显示5 去掉升级位 置:HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer键值名:NoCommonGroups取 值:1为隐藏、0为显示6 去掉“文档”位 置:HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer键值名:NoRecentDocsMenu取 值:1为隐藏、0为显示7 自动清除“文档”位 置:HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer键值名:ClearRecentDocsOnExit取 值:1为自动清除、0为不自动清除8 去掉“查找”位 置:HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer键值名:NoFind取 值:1为隐藏、0为显示9 锁定“文档”位 置:HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer键值名:NoRecentDocsHistory取 值:1为锁定、0为不锁定10 去掉“运行”位 置:HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer键值名:NoRun取 值:1为隐藏、0为显示11 搜索“自启动”程序位 置:HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run在注册表内,我们可以查询系统启动后加载了哪些程序。 单击注册表内的目录树,这里最重要的是“装载源”,从“软件环境”、“启动程序”显示的结果看,绝大多数“自启动”程序都是通过注册表加载的,即“装载源”显示为“Registry (Machine Run)”的程序。 12 去掉“注销”位 置:HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer键值名:NoLogOff取 值:1为隐藏、0为显示13 缩短“新建”选项当你用鼠标右键点击资源管理器空白处,并选取新建菜单时,会弹出建立多种程序文件的菜单,但是里面有一些你可能并不常用,比如现在我要去除掉菜单中的“Wave Sound”项目,来缩短菜单。 打开注册表,请选择查看下的搜索项,然后输入“shellnew”,并选择“全字匹配”选项;在HKEY_LOCAL_MACHINE与HKEY_LOCAL_ROOT下进行查找,找到后将该其下面的shellnew子键删除掉即可。 14 清除配色方案位 置:HKEY_CURRENT_USER\Control Panel\Appearance\Schemes首先请找到该子键,在窗口的右边会出现系统自带的各种配色方案,将你认为无用的配色方案删除掉,一般只保留“Windows默认”一项。 然后再打开“控制面板”窗口中的“显示”,然后在“显示 属性”窗口中单击“外观”标签,在“窗口配色方案”下拉列表中进行查看。 15 修改桌面图标例如,我们修改Windows桌面上“回收站”的名字及图标,可执行如下操作步骤。 位 置:HKEY_CLASSES_ROOT\CLSID\{645FF040-5081-101B-9F08-00AA002F954E}先打开注册表编辑器;然后根据上面提供的位置找到该主键,双击窗口右边的“回收站”,弹出字符串编辑器, 然后在文本输入框内,将“回收站”改为“垃圾筒”, 重新启动机器后,桌面上的回收站就变成了垃圾筒,但图标依旧!单击{645FF040-5081-101B-9F08-00AA002F954E}前面的“+”,则展开这个主键,在它下面还有一个子键DefaultIcon。 然后单击此子键,在右窗格中的“数据”栏下将出现三个图标文件名,分别为“$#@60;未命名$ 2;”、“Full”(满)、“Empty”(空)的回收站图标,这三个图标包含在动态链接库文件里面,图标资源所在的序号分别是31、31、32, 其数据格式是“C:\Windows\System\,31”等(调用动态链接库中的图标资源,采用这种格式就可以啦!)。 如果您想把它改成自己的图标,则只要将此数据改为自己图标或者动态链接库即可,例如使用图标文件为“C:\Windows\”,这样再重新启动机器就可以看到垃圾筒的图标被改变了。 利用同样的方法可以修改桌面上其它的图标和文字。 16 删除“系统”当你想删除桌面上的“回收站”、“Internet Explorer”等图标时,会发现它们不能用一般的方法删除。 这时还可以通过修改注册表来办到。 位 置:HKEY_LOCAL_ MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Desktop\NameSpace在该分支下面有多个子键,这些子键将对应桌面上的“系统”图标,在窗口右边你就可以看到。 删除不需要的图标,即对应的键值;重新启动后,会看到桌面上的一些图标不见啦!17 隐藏桌面位 置:HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion \Policies\Explorer键值名:NoDesktop取 值:0、1这种隐藏桌面图标的方法与简单地在“显示 属性”窗口内,使用“Active desktop”下的隐藏图标的方法不一样。 这里的隐藏除了将图标隐藏外,连整个桌面都一并隐藏了起来,并且同时禁止了在桌面上点击鼠标右键功能。 18 去掉“网上邻居”位 置:HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer键值名:NoNetHood取 值:1为隐藏、0为显示19 关闭系统版本号位 置:HKEY_CURRENT_USER\Control Panel\desktop键值名:PaintDesktopVersion取 值:0为隐藏、1为显示说 明:它能把你的Windows的版本号在桌面的右下角显示出来,如果你使用的是测试版, 那么就可以将桌面右下角的文字去掉。 20 隐藏指定驱动器位 置:HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer键值名:NoDrives取 值:需要说明一下,在这里使用的是2的N次方来代表一个驱动器名称,而非寻常的A、B、C、D……,下面就给出各驱动器名与2的N次方的对应关系,以方便读者:A: 1, B: 2,C: 4, D: 8, E: 16, F: 32, G: 64,H: 128, I: 256,J: 512,K: 1024, L: 2048, M: 4096, N: 8192,O: , P: , ,R: ,S: ,T: , U: , V: , W,X: , Y: , Z: 按照上面的取值规则,如果你要隐藏A、B、C三个驱动器,输入7即可,因为7=1+2+4,如果你要隐藏所有驱动器,输入。 21 修改“回收站”位 置:HKEY_CLASSES_ROOT\CLSID\{645FF040-5081-101B-9F08-00AA002F954E}\ShellFolder键值名:Attributes取 值:40 01 00 20、70 01 00 20说 明:缺省情况下是40 01 00 20,把它改为70 01 00 20后,就可以把桌面上的“回收站”象资源管理器内的文件一样,能任意地更名或者删除了。 22 修改桌面位 置:HKEY_CURRENT_USER\ControlPanel\desktop说 明:打开注册表编辑器,然后打开该分支。 在此分支右窗格内可以看到一些项目,现介绍几个如下:HungAppTimeout:这是指一个应用程序出错时试图等待响应的时间,值为毫秒,缺省值为5000毫秒(即5秒),可以减少为3000毫秒,以加快系统的响应能力。 MenuShowDelay:这是指“开始”菜单中当鼠标指向一个具有下级 菜单的菜单项时等待出现下级菜单的延迟时间,单位也是毫秒,可以设成100,即等待0.1秒就会出现(前面已经提到过)。 ScreenSaveActive:这是现在屏幕保护功能是否可用,值为0或1,0即为不用屏幕保护功能,1为可用,但必须你已经使用了屏幕保护功能。 ScreenSaveTimeOut:这是指屏幕保护的延时,值类型为一个数值。 单位是秒,最小值是60秒,但必须你已经使用了屏幕保护功能;如果你将数值改为1,那么每停顿1秒钟,便会启动屏幕保护。 WaitToKillAppTimeout:这是指当按下 Crtl+Alt+Del后以后,出现“关闭程序”对话框,出现提示“结束任务”、“等待”时选择“等待”的等待时间,单位是毫秒,默认值是。 可以减少等待时间。 23 定制按钮颜色尽管Windows在外观中可以定义多种窗口显示方案,但要定义某一个部位的颜色,如将黑色的按钮字体改变为其它的颜色, 它就无能为力啦!通过修改注册表能很容易实现。 在注册表内找到HKEY_CURRENT_USER\Control Panel\Colors的子键,然后将窗口右边的“Bottontext”键值由原来的“0 0 0”改为“255 0 0”(代表红色)。 24 汉字后加空格位 置:HKEY_CURRENT_USERS\Software\Microsoft\Windows\CurrentVersion键值名:插空格取 值:0不插入空格、1插入空格25 活用Enter键位 置:HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVer n键值名: 取 值:0保留原功能,输入法不处理、1等同于Esc键,用于清除当前外码输入状态说 明:当取值为1时,如果有候选窗口,会自动隐藏输入窗口,清除所有外码,但不隐藏外码输入窗口。 当无候选窗口,清除外码,并隐藏外码输入窗口。 26 活用Space键位 置:HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion键值名: 取 值:0指明这是作为结束外码输入的标志键,这种设置适合于形码、1指明这是作为候选选择键,这种设置适合于音码。 27 系统时间格式 位 置:HKEY_CURRENT_USER\ControlPanel\International键值名:sTimeFormat取 值:H:mm:ss、HHmm不等说 明:在通常情况下,Windows在任务栏中使用“23:12”的时间格式来显示时间, 但是您可以通过修改注册表编辑器来更改此时间格式。 28 更改登录背景位 置:HKEY_USERS\\Control Panel\Desktop键值名:Wallpaper取 值:目标背景图文件路径29 修改注册码位 置:HKEY_LOCALMACHINE\Software\Microsoft\Windows\CurrentVersion键值名:ProductId取 值:任意字符30 禁止自动运行在通常情况下,绝大多数在Windows启动时自动运行的应用程序有如下两种设置办法:在“启动”程序组中添加快捷方式 如果使用的是这种方法。 则我们只需将它们的快捷方式从 “启动”程序组中删除即可达到禁止它们自动运行的目的。 修改Windows的注册表数据库如果您使用过一些诸如CD播放机等的用户都知道,在使用这些软件时,都将在任务栏右边 将出现一个图标,这有时会带来不便。 其实,这些软件的自启动程序的注册项放在HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run分支中。 您只要到此分支中找出对应的自启动程序即可,另外,在“Run”主键下还可能有“SysExplr”子键。 如果有该子键,可以将其中的内容清空,同样也能取消Windows启动时自启动的程序。 那么反过来,我们怎样在注册表内添加自启动程序呢?先找到 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run主键,然后在它的窗口右边建立一 个名为“SysExplorer”的键值名,并将其值设为“”,退出注册表编辑器,注销用户后重新启动计算机,系统将自动运行资源管理器。 另外Windows还提供了一次性的自启动功能。 紧跟在“Run”主键后面有一个“RunOnce”和“RunOnceEx”子键,你可以在这两个子键内设置新的键值,让系统自动运行一次某个程序,即仅在下一次启动Windows时才有效。 31 软件显示乱码 解决的方法是在注册表内找到HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\fontassoc\Associated CharSet位置,将窗口右边内的“SYMBOL(02)” 键值(这是系统的机内码)改为“NO”即可。 32 删除软件的残骸每一个Windows操作系统的的使用者可能都有这样的经历,由于种种原因直接在硬盘中删除了某个文件夹,或者是在“添加/删除程序”里面对一些软件进行反安装。 但是有些程序却还有注册信息留在注册表内,当你再次从“添加/删除程序”中卸载该程序时,老是提示“试图删除XXXXXX时出错,放弃卸载”,从而导致了卸载程序错误。 当机器中安装大量的软件后随着时间的后移,就在系统的注册表中就形成了垃圾,影响了机器的运行速度。 下面介绍彻底清除这些垃圾的方法。 用注册表编辑器来清除注册表中关于卸载应用程序的相关键值数据HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall位置,一般的软件在注册表内的反安装子键里有“DisplayName”、“UninstallString”这两个键值,第一个显示的是软件的名称、第二个 显示的是反安装的一些信息。 双击第二个键值后,便会明白反安装是怎么回事,反安装实际上是你所安装的软件自带有一个反安装程序,在安装该软件时,它会自己记录一些安装信息存放文件中,卸载时用这个反安装程序再带上文件的参数即可。 另外,有些软件反安装时使用的是系统提供的反安装程序。 再如,许多应用软件在卸载之后仍会在注册表文件内留下一些无用信息。 比较集中的地方在HKEY_LOCAL_MACHINE\Software、HKEY_CURRENT_USER\Software和HKEY_USERS\ \Software。 这几项里面的内容基本上一致,在其中一处作查找删除就行了。 比较常用到的方法是进入HKEY_LOCAL_MACHINE\Software分支中,然后重点查找那些已经确信被安全卸载了的软件的残留信息,在确认无误后删除。 33 恢复CD Key如果你不小心将Windows的CDKey丢失了,担心在以后需要安装系统时会遇到什么麻烦。 我该如何才能找回它呢?您可以从NT的注册表中找到这个CDKey。 打开注册表,然后再找到“HKEY_LOCAL_MACHINE\SOFTWARE\Microso WindowsNT\CurrentVersion”位置,在右侧的ProductId键值中,就包含了CDKey的信息,另外,如果您所使用的NT是OEM版本,则有可能整个ProductId的串值就是CDKey!34 加入登录信息因为加入这样的功能需要修改NT的注册表,所以请您小心并做好备份。 首先在注册表中的找到HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Winlogon子键,然后在窗口右边找到“LegalNoticeCaption”和“LegalNoticeText”两个键值。 如果没有, 请添加这两个键值。 然后在这两个键值内分别输入“这是我的服务器”、“欢迎光临!”。 关闭注册表,重启机器,这次您就看到在登录窗口之前,将会出现一个新的窗口,包含上面您所输入的这两条信息。 35 防范非法入侵介绍如何防止本地用户非法入侵 Windows NT 系统的文章已经并不少见,但如何防范远程用户呢?当然,一般的做法是,可以在用户拨号进入系统(或通过局域网进入系统)时限制其对文件的访问权限,以达到保护文件的目的。 但毕竟这种安全级别不够高,如何能将这些用户锁在系统的门外,以达到绝对安全的目的呢?NT为驱动器和系统目录创建默认共享的目的,是为了使系统管理员、备份程序和其他授权用户及服务性工作能顺利访问其他个人用户的文件。 当其他用户访问您的系统时这些共享对象并不显现出来。 但是任何一个远程 用户只要知道这些共享对象的确切名称,并且有访问权的话,他就可以与这些共享对象建立连接。 令人遗憾的是,NT系统的安全机制非常脆弱。 虽然SecurityPack5的出台为老用户提高到管理员水平而提供了一些补漏措施,并且还 有一些NT的安全检查方法,但仍然还会有其他漏洞存在。 所以如果您的计算机在局域网上,或者是通过Modem连接 上网的,那么可通过取消这些组件的共享来保护数据。 为了达到此目的,打开NT的注册表编辑器。 在注册表编辑 器中,将当前目录定位在HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\lanmanagerServer\parameters,如果没有AutoShareWks键值名,那么请你新建立一个;然后再双击它并输入“3D0”,最后单 “确定”按钮、关闭注册表编辑器,然后重新启动计算机。 36 ICQ中有“漏洞”ICQ是由以色列一家叫Mirabilis的公司出品的网络软件,其作用是为Internet上的用户提供实时的信息传递服务。 有了它,你就可以同千里之外的朋友交流信息,还可以在对方不在线的情况下“呼叫” 他(她)上线,难怪广大网友都亲切地叫它“网络寻呼机”。 但是,你是否知道在ICQ for Windows版本中 有一个“漏洞”。 ICQ在Windows注册表中有一个键值被称为“Auto Update”(自动更新)。 如果该键值被设 置成“Yes”,那么每一次登录到服务器的时候,就会将你的计算机中一些重要信息发送到登录的服务器上。 这些信息包括:你正在使用的操作系统类型、版本、序列号、用户登记名称、公司名称、所使用的浏览器版本等等。 这些重要信息的发送可能会被黑客或某些别有心的人所利用,给你带来不必要的麻烦。 为了避免此问题的发生可采用修改注册表关掉ICQ的“自动更新”功能。 首先在注册表内找到 HKEY_CURRENT_USER\Software\Mirabilis\ICQ\DefaultPrefs位置,并在窗口右边找到“Auto Update”键值; 将“Auto Update”键值由“Yes”修改为“No”即可。 为了你系统的稳定性,在进行修改时请注意要在关闭ICQ 应用程序的情况下进行修改。 修改完毕后,请重新启动计算机。 37 增加执行文件路径如果需要运行的程序不在指定的目录中,则DOS系统一般采用在自动批处理文件中设置路径的方法来达到自动寻找此程序的目的;在Windows中则可以更秘密地增加程序路径,而不是通过设置自动批处理的方式,这就需要通过修改注册表来实现上述目的。 比如要为“C:\ProgramFiles\pdoc\”文件增加路径。 先打开注册表,然后找到HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\AppPATHs的位置,在窗口右边新建一个名为“”的主键,选择该主键,将其默认值设为“C:\ProgramFiles\pdoc\”;再新建名为“Path”的主键,将其设为“C:\ProgramFiles\pdoc”。 这样就可以通过在“运行”命令行中键入“” 或“pdoc”来运行该程序了。 另外你还可以为已经存在的程序设置新的主键,比如可以为MicrosoftWord 97添加名称为“”的主键。 假设Word 97安装在“C:\ProgramFiles\MicrosoftOffice\Office\”目录中,则其操作为:打开注册表,在“我的电脑”文件夹中依次选择“HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\AppPaths”,新建名称为“”主键,选择该主键,将其默认值设为“C:\ProgramFiles\MicrosoftOffice\Office\”即可,建立执行目录的方法与上例一样。 38 更改系统安装目录如果使用光盘安装Windows,当添加新的硬件时,系统配置驱动程序时会提醒需要在光驱中插入Win 98光盘,而且每次都 要这样做,的确太麻烦了。 您可以将Win 98安装盘中的所有“*”文件都拷贝到硬盘的某个目录下,比如“D:\Backup\PWin98”,然后运行注册表编辑器,在“我的电脑”文件夹中依次选择“HKEY_LOCAL_MACHINE”、“Software”、“Microsoft”、“Windows”、“CurrentVersion”、“Setup”,将“SourcePath”主键的值改为“D:\Backup\PWin98\”,重新启动计算机即可。 如果网络上有一个文件服务器,假定Win98安装盘备份在“D:\Backup\PWin98\”目录中,文件服务器的机器名为“MMX233”,D盘共 享名为“DiskD”,则将“SourcePath”主键值改为“\\MMX233\DiskD\Backup\PWin98\”,注销用户或重新启动Windows即可。 39 去掉IE内的分级审查口令首先找到在注册表的HKEY_LOCAL_MACHINE\Software\Microsoft\Windows \Currentversion\Policies\Ratings位置,这里保存的是IE下“Internet属性”对话框的“内容”选项页中的“分级审查”中的口令,该口令是经过加密的,在下图中你可以看到记录该口令的有两个键值,而二进制的“key”键值则是加过密的,去掉口令的方法即是将子键下的这两个键值删除,如果没有口令,这个子键无键值。 下次进入IE,你就可以安全地进入分级审查,并且可以直接跳过输入“旧密码”,直接加入密码即可.40 设置中文Windows内的系统语言如果你安装了一个英文游戏,并且不支持中文,例如QUAKE。 就可以将中文Windows内的汉字按照英文一样来处理。 比如每个汉字都被当成了两个字符来处理,删掉一个汉字也需要按两下删除键,而且每到行末,就会出现汉字丢掉一半的奇怪现象。 如果遇到这样的情况,千万别着急重新安装Windwos,你还可以先试一试下面的方法。 首先在注册找到HKEY_LOCAL_MACHINE\System\CurrentControlSet\control\Nls\Locale的位置,将原来的“”改为默认的“”(系统默认使用的语言系统).41 更改IE标题栏中的文字首先在注册表中找到下面的位置HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Main,然后再新建一个字符串值,将其命名为Window Title(注意两个词中间有一个空格).42 如何删除多余的DLL文件在WIN98的System子目录下存有大量的DLL文件,这些文件可能被系统或应用程序共享。 但是由于经常安装和卸载软件,就会在System目录下留下一些DLL垃圾文件。 它们不但占用了硬盘空间,而且还降低系统的运行速度。 删除它们的步骤如下:1.运行“REGEDIT”, 打开注册表编辑器。 2.打开HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\SharedDLLs分支。 这里SharedDLLs子键记录的就是有关程序共享的DLL信息,每个DLL文件的键值说明它已被几个应用程序共享。 如果是二进制键值为“00 00 00 00”,则表明不被任何程序共享。 (另外“0x (1)”是十六进制表示法)3.System目录中删除对应的文件。 43 去掉桌面快捷方式的小箭头在一些程序的安装过程中,会自动在桌面上创建该程序的快捷方式,方便了我们的使用。 但是那个小箭头不太好看。 我们可以利用修改注册表来去掉它。 首先要注意此快捷方式是什么类型的,一般说来以居多,也有一些是(指向MS-DOS程序的快捷方式)。 具体步骤如下:1.运行注册表编辑器,打开HKEY_CLASSES_ROOT\lnkfile分支。 2.在lnkfile子键下面找到一个名为“IsShortcut”的键值,它表示在桌面的快捷方式图标上将出现一个小箭头。 右键单击“IsShortcut”,然后从弹出的菜单中选择“删除”,将该键值删除。 3.关闭注册表编辑器,重新启动Win98,就可发现快捷方式图标上已经没有小箭头了。 同理,对指向MS-DOS程序的快捷方式(即)图标上的小箭头,则除了是打开HKEY_CLASSES_ROOT\piffile分支外,其余同上。
……如果是输入一行字符串的话,没必要定义999个字节的字符串,浪费空间,其余的就是你不能边转换便输出吗?那样可以省掉一次对于链表的访问,暂时就这些想法,希望有帮助
一、Debug 和 Release 编译方式的本质区别 Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序。 Release 称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用。 Debug 和 Release 的真正秘密,在于一组编译选项。 下面列出了分别针对二者的选项(当然除此之外还有其他一些,如/Fd /Fo,但区别并不重要,通常他们也不会引起 Release 版错误,在此不讨论)Debug 版本: /MDd /MLd 或 /MTd 使用 Debug runtime library(调试版本的运行时刻函数库) /Od 关闭优化开关 /D _DEBUG 相当于 #define _DEBUG,打开编译调试代码开关(主要针对 assert函数) /ZI 创建 Edit and continue(编辑继续)数据库,这样在调试过 程中如果修改了源代码不需重新编译 /GZ 可以帮助捕获内存错误 /Gm 打开最小化重链接开关,减少链接时间 Release 版本: /MD /ML 或 /MT使用发布版本的运行时刻函数库 /O1 或 /O2优化开关,使程序最小或最快 /D NDEBUG 关闭条件编译调试代码开关(即不编译assert函数) /GF 合并重复的字符串,并将字符串常量放到只读内存,防止 被修改 实际上,Debug 和 Release 并没有本质的界限,他们只是一组编译选项的集合,编译器只是按照预定的选项行动。 事实上,我们甚至可以修改这些选项,从而得到优化过的调试版本或是带跟踪语句的发布版本。 二、哪些情况下 Release 版会出错 有了上面的介绍,我们再来逐个对照这些选项看看 Release 版错误是怎样产生的 1. Runtime Library:链接哪种运行时刻函数库通常只对程序的性能产生影响。 调试版本的 Runtime Library 包含了调试信息,并采用了一些保护机制以帮助发现错误,因此性能不如发布版本。 编译器提供的 Runtime Library 通常很稳定,不会造成 Release 版错误;倒是由于 Debug 的 Runtime Library 加强了对错误的检测,如堆内存分配,有时会出现 Debug 有错但 Release 正常的现象。 应当指出的是,如果 Debug 有错,即使 Release 正常,程序肯定是有 Bug 的,只不过可能是 Release 版的某次运行没有表现出来而已。 2. 优化:这是造成错误的主要原因,因为关闭优化时源程序基本上是直接翻译的,而打开优化后编译器会作出一系列假设。 这类错误主要有以下几种: (1) 帧指针(Frame Pointer)省略(简称 FPO ):在函数调用过程中,所有调用信息(返回地址、参数)以及自动变量都是放在栈中的。 若函数的声明与实现不同(参数、返回值、调用方式),就会产生错误————但 Debug 方式下,栈的访问通过 EBP 寄存器保存的地址实现,如果没有发生数组越界之类的错误(或是越界“不多”),函数通常能正常执行;Release 方式下,优化会省略 EBP 栈基址指针,这样通过一个全局指针访问栈就会造成返回地址错误是程序崩溃。 C++ 的强类型特性能检查出大多数这样的错误,但如果用了强制类型转换,就不行了。 你可以在 Release 版本中强制加入 /Oy- 编译选项来关掉帧指针省略,以确定是否此类错误。 此类错误通常有: ● MFC 消息响应函数书写错误。 正确的应为afx_msg LRESULT OnMessageOwn(WPARAM wparam, LPARAM lparam);ON_MESSAGE 宏包含强制类型转换。 防止这种错误的方法之一是重定义 ON_MESSAGE 宏,把下列代码加到 stdafx.h 中(在#include afxwin.h之后),函数原形错误时编译会报错#undef ON_MESSAGE#define ON_MESSAGE(message, memberFxn) \{ message, 0, 0, 0, AfxSig_lwl, \(AFX_PMSG)(AFX_PMSGW)(static_cast< LRESULT (AFX_MSG_CALL \CWnd::*)(WPARAM, LPARAM) > (&memberFxn) },(2) volatile 型变量:volatile 告诉编译器该变量可能被程序之外的未知方式修改(如系统、其他进程和线程)。 优化程序为了使程序性能提高,常把一些变量放在寄存器中(类似于 register 关键字),而其他进程只能对该变量所在的内存进行修改,而寄存器中的值没变。 如果你的程序是多线程的,或者你发现某个变量的值与预期的不符而你确信已正确的设置了,则很可能遇到这样的问题。 这种错误有时会表现为程序在最快优化出错而最小优化正常。 把你认为可疑的变量加上 volatile 试试。 (3) 变量优化:优化程序会根据变量的使用情况优化变量。 例如,函数中有一个未被使用的变量,在 Debug 版中它有可能掩盖一个数组越界,而在 Release 版中,这个变量很可能被优化调,此时数组越界会破坏栈中有用的数据。 当然,实际的情况会比这复杂得多。 与此有关的错误有: ● 非法访问,包括数组越界、指针错误等。 例如 void fn(void) { int i; i = 1; int a[4]; { int j; j = 1; } a[-1] = 1;//当然错误不会这么明显,例如下标是变量 a[4] = 1; } j 虽然在数组越界时已出了作用域,但其空间并未收回,因而 i 和 j 就会掩盖越界。 而 Release 版由于 i、j 并未其很大作用可能会被优化掉,从而使栈被破坏。 3. _DEBUG 与 NDEBUG :当定义了 _DEBUG 时,assert() 函数会被编译,而 NDEBUG 时不被编译。 除此之外,VC++中还有一系列断言宏。 这包括: ANSI C 断言 void assert(int expression );C Runtime Lib 断言_ASSERT( booleanExpression );_ASSERTE( booleanExpression );MFC 断言ASSERT( booleanExpression );VERIFY( booleanExpression );ASSERT_VALID( pObject );ASSERT_KINDOF( classname, pobject );ATL 断言ATLASSERT( booleanExpression );此外,TRACE() 宏的编译也受 _DEBUG 控制。 所有这些断言都只在 Debug版中才被编译,而在 Release 版中被忽略。 唯一的例外是 VERIFY() 。 事实上,这些宏都是调用了 assert() 函数,只不过附加了一些与库有关的调试代码。 如果你在这些宏中加入了任何程序代码,而不只是布尔表达式(例如赋值、能改变变量值的函数调用 等),那么 Release 版都不会执行这些操作,从而造成错误。 初学者很容易犯这类错误,查找的方法也很简单,因为这些宏都已在上面列出,只要利用 VC++ 的 Find in Files 功能在工程所有文件中找到用这些宏的地方再一一检查即可。 另外,有些高手可能还会加入 #ifdef _DEBUG 之类的条件编译,也要注意一下。 顺便值得一提的是 VERIFY() 宏,这个宏允许你将程序代码放在布尔表达式里。 这个宏通常用来检查 Windows API 的返回值。 有些人可能为这个原因而滥用 VERIFY() ,事实上这是危险的,因为 VERIFY() 违反了断言的思想,不能使程序代码和调试代码完全分离,最终可能会带来很多麻烦。 因此,专家们建议尽量少用这个宏。 4. /GZ 选项:这个选项会做以下这些事 (1) 初始化内存和变量。 包括用 0xCC 初始化所有自动变量,0xCD ( Cleared Data ) 初始化堆中分配的内存(即动态分配的内存,例如 new ),0xDD ( Dead Data ) 填充已被释放的堆内存(例如 delete ),0xFD( deFencde Data ) 初始化受保护的内存(debug 版在动态分配内存的前后加入保护内存以防止越界访问),其中括号中的词是微软建议的助记词。 这样做的好处是这些值都很大,作为指针是不可能的(而且 32 位系统中指针很少是奇数值,在有些系统中奇数的指针会产生运行时错误),作为数值也很少遇到,而且这些值也很容易辨认,因此这很有利于在 Debug 版中发现 Release 版才会遇到的错误。 要特别注意的是,很多人认为编译器会用 0 来初始化变量,这是错误的(而且这样很不利于查找错误)。 (2) 通过函数指针调用函数时,会通过检查栈指针验证函数调用的匹配性。 (防止原形不匹配)(3) 函数返回前检查栈指针,确认未被修改。 (防止越界访问和原形不匹配,与第二项合在一起可大致模拟帧指针省略 FPO )通常 /GZ 选项会造成 Debug 版出错而 Release 版正常的现象,因为 Release 版中未初始化的变量是随机的,这有可能使指针指向一个有效地址而掩盖了非法访问。 除此之外,/Gm /GF 等选项造成错误的情况比较少,而且他们的效果显而易见,比较容易发现。 三、怎样“调试” Release 版的程序 遇到 Debug 成功但 Release 失败,显然是一件很沮丧的事,而且往往无从下手。 如果你看了以上的分析,结合错误的具体表现,很快找出了错误,固然很好。 但如果一时找不出,以下给出了一些在这种情况下的策略。 1. 前面已经提过,Debug 和 Release 只是一组编译选项的差别,实际上并没有什么定义能区分二者。 我们可以修改 Release 版的编译选项来缩小错误范围。 如上所述,可以把 Release 的选项逐个改为与之相对的 Debug 选项,如 /MD 改为 /MDd、/O1 改为 /Od,或运行时间优化改为程序大小优化。 注意,一次只改一个选项,看改哪个选项时错误消失,再对应该选项相关的错误,针对性地查找。 这些选项在 Project\Settings... 中都可以直接通过列表选取,通常不要手动修改。 由于以上的分析已相当全面,这个方法是最有效的。 2. 在编程过程中就要时常注意测试 Release 版本,以免最后代码太多,时间又很紧。 3. 在 Debug 版中使用 /W4 警告级别,这样可以从编译器获得最大限度的错误信息,比如 if( i =0 )就会引起 /W4 警告。 不要忽略这些警告,通常这是你程序中的 Bug 引起的。 但有时 /W4 会带来很多冗余信息,如 未使用的函数参数 警告,而很多消息处理函数都会忽略某些参数。 我们可以用#progma warning(disable: 4702) //禁止//...#progma warning(default: 4702) //重新允许来暂时禁止某个警告,或使用#progma warning(push, 3) //设置警告级别为 /W3//...#progma warning(pop) //重设为 /W4来暂时改变警告级别,有时你可以只在认为可疑的那一部分代码使用 /W4。 4.你也可以像 Debug 一样调试你的 Release 版,只要加入调试符号。 在 Project/Settings... 中,选中 Settings for Win32 Release,选中 C/C++ 标签,Category 选 General,Debug Info 选 Program Database。 再在 Link 标签 Project options最后加上 /OPT:REF (引号不要输)。 这样调试器就能使用 pdb 文件中的调试符号。 但调试时你会发现断点很难设置,变量也很难找到——这些都被优化过了。 不过令人庆幸的是,Call Stack 窗口仍然工作正常,即使帧指针被优化,栈信息(特别是返回地址)仍然能找到。 这对定位错误很有帮助。
不懂移动端开发,也可以贡献移动端代码。
无限增强FinClip小程序安全运行沙箱FinClip小程序安全运行沙箱,以SDK的方式供App开发者嵌入,让自己的App秒变能运行小程序的超级App。 在这里,“App”还不仅仅是指iOS或者Android的应用,宿主可以强大至配备多核CPU和较多内存的PC,也可以是运算能力比较有限的嵌入式设备(embeddeddevices),例如一个带触摸屏的RaspberryPI。
宿主硬件环境和软件环境都各有不同,需要暴露给小程序利用的功能不一样;此外,不同的商业环境下,应用所集成的原生能力(例如地图、支付、加密、音视频、甚至AR/XR等)也不同。 FinClip支持开发者自定义各种API接口,注入至FinClipSDK中,从而以JavaScript的方式供小程序开发者调用。
通过这种方式,任何小程序理论上可利用所在宿主环境的任何技术能力,而不仅受限于FinClipSDK所提供的标准接口。
官方支持的自定义接口扩展方式当前FinClip官方支持的自定义接口,需要用所在宿主环境的原生技术实现,例如在iOS上需要用Objective-C或Swift开发,在Android上则是采用Java/Kotlin等。 这个做法就需要起码两个平台的工程师分别开发-当然过去以来这也不是问题,任何手机端App都不得不维持两队人马搞两个版本。 但是当你有更多类型的终端要支持的时候,就很麻烦了。
正如在《FinClip小程序+Rust》这个系列所提到,对于纯逻辑类、算法类的功能例如音视频编码的处理、加解密等等,完全没有人机交互的部分,采用一个跨平台的通用语言来实现,更加便利。 但是我们又都不想去折腾C的代码,Rust是一个很好的选择。 作为一种新兴的、内存安全、线程安全的语言,Rust可跨平台编译,高性能、体积小,尤其适合于设备端的编程,包括在低算力、低功耗、低内存的IoT设备上开发Heapless代码;并且,Rust已经是Android官方支持的系统语言。
那么,FinClip能否支持开发者用Rust提供对其安全运行沙箱的自定义扩展呢?
先看一下FinClip环境下的技能分工与协同回答上述问题前,在这里我们先想象一下,假如在一个端到端的应用软件生产链路上,以FinClip技术为各环节的“粘合剂”,一个新型的技术小组的角色(技能)组成是怎样的:
iOS/Android/其他终端的“宿主”开发工程师:负责宿主“壳”应用的开发,以及FinClipSDK集成。需要懂ObjC/Swift、Java/Kotlin、乃至Electron/Qt/C++,视乎所要支持的目标操作系统
FinClip小程序开发工程师:负责各种业务功能的前端开发,懂HTML/JavaScript以及一些前端框架即可
FinClipSDKExtension开发工程师:负责实现一些通用的逻辑算法、底层的基础设施,供各目标终端的“宿主”应用集成。需要掌握Rust编程
DevOps工程师:如果打算自行运行维护自己的FinClip小程序中心、管理自己的小程序开发者和开发生态,那么就需要工程师去部署运行FinClip服务器端
这是一条起码的“流水线”,各个岗位用不同的语言技能,分工越清晰越好,哪怕这些事情都是同一个人“包打天下”了,也需要自己明确在不同角色下做不同的事,有助于梳理出合理的架构,在一个端到端的技术链路上,界定好每一个环节的功能范畴。
Gluecode和生态FinClip这门技术,单纯从软件工程角度看,它扮演的是gluecode(粘合剂)的角色,把一个涉及多种语言、多类技术的软件系统粘合起来。 Gluecode往往是最繁琐、也最容易出错的地方,把这个层面的技术解决好了,能大大释放开发者的生产力和创造力。 相当于流水线搭建好了,每个环节都可以独立润滑、丰富、加强。 而且每个环节都变得更加专业,甚至形成自己的零部件“供应链”。
例如,把HTML/JavaScript部分的技术,和设备端原生技术对接好,就引入了大量的可以专注于小程序开发的工程师提供丰富的应用场景;把设备端原生技术中跨设备通用的逻辑解耦出来成为可插拔的“插件”,又可以进一步促生仅聚焦这一部分工作的人,产出丰富、高品质的插件。 只要标准化,就有机会形成生态。
提供端到端的应用解决方案,变成是“集大成”,在技术链路各环节的“供应链”中,选取自己需要的零部件,去组装自己的应用。
插件开发者:用Rust实现FinClipSDK的“插件”正如FinClip小程序的开发者无需懂得任何iOS/ObjC/Swift、Android/Java/Kotlin的技能知识,仅凭对HTML/JavaScript的掌握即可开发出有用的应用一样,FinClipSDKExtension的开发者,最好也无需了解太多操作系统平台的编程知识,甚至无需跟ObjC、Java打交道,即可开发出自己的扩展。
我们在技术是可以做到的。 按以下的步骤-注意下述内容都发生在Rust这侧,对ObjC/Java空间的代码开发要求为零。
准备构建一个静态库所需的环境用cargo创建一个lib类型的项目,例如
cargo?new?--lib?myplugin然后修订一下所生成的:
[package]name?=?mypluginversion?=?0.1.0edition?=?2021[lib]name?=?myplugin#?this?is?needed?to?build?for?iOS?and?-type?=?[staticlib,?lib][dependencies]serde_json?=?1.0.81??#?建议使用这个crate实现json对象序列化#?其他你准备封装或者依赖的crate定义准备注入至FinClip的API在src/,开始定义和封装你计划提供给原生宿主应用开发者注入至其FinClipSDK的函数。
首先,定义一个新的类型:
type?FinClipCall?=?fn(&String)?->?String;这个类型名字请命名为FinClipCall,且这个类型所表示的函数签名,必须是:
fn(&String)?->?String它实际上是一个函数指针,它能够指向这样的函数,例如:
fn?invoke(param:?&String)?->?String?{...}注意这个类型的函数,期望的输入参数是一个合法的JSON字符串,返回的也必须是一个合法的JSON字符串。 因为FinClip的自定义API,统一用JSON作为入参和出参,便于小程序侧JavaScript代码的处理。 所以在上文推荐引入serde_json这个crate,帮助做一些JSON相关的数据转换。
其次,开始实现你的函数实现,例如:
fn?api_drinker(input:?&String)?->?String?{????//?先处理一下入参,把进来的字符串检测为合法JSON对象,????//?再用serde_json把它转化为某个类型的参数对象,供后续使用????println!(invoked?with?parameter?{},?input);????//中间的逻辑算法从略,这里应该是你自己的算法,产生的结果对象,可以????//用serde_json进行Json?serialization????let?john?=?json!({????????name:?john?doe,????????phones:?????});????_string()}fn?api_whisky(input:?&String)?->?String?{????//?先处理一下入参,把进来的字符串检测为合法JSON对象,????//?再用serde_json把它转化为某个类型的参数对象,供后续使用????println!(invoked?with?parameter?{},?input);????//中间的逻辑算法从略,这里应该是你自己的算法,产生的结果对象,可以????//用serde_json进行Json?serialization????let?brands?=?json!({????????whisky:?{????????????jack:?daniel,????????????johny:?walker,????????????henry:?Mckenna,????????????suntory:?toki????????}????});????_string()}以上以此类推,按类似的签名来实现你的API。
文字命名你的API名称并造册登记“花名”FinClip小程序侧,调用自定义API的办法,是通过API的名字。 例如你把一个API接口命名为abc,那么这个接口被注入到FinClipSDK后,它在JavaScript侧的调用,就是(...)。
在此,你需要给每一个自定义函数一个文本命名,并映射它们的关系,这确实有点像代码编译器里面的virtualtable。这里,是我们开发的这个myplugin项目中另一个需要注意一下的地方:
pub?unsafe?extern?C?fn?myplugin_register_apis()?->?*mut?HashMap这个函数做了什么事情呢?虽然只有几行代码,有必要解释一下:
首先,我们初始化了一个HashMap,这个HashMap的Key和Value的类型,分别是String和之前我们自定义的函数指针类型FinClipCall
其次,开始造“花名册”,也就是直接粗暴的穷举所有要输出的函数,把它们塞到HashMap,完成造册
最后,是比较“技巧性”的地方,就是如何把这个HashMap对象返回出去。 记得我们的这些函数,最终必须暴露给iOS、Android等平台上的宿主应用,以便于这些应用的开发者,把这些函数注入到FinClipSDK,所以这里是你的Rust代码和你的合作伙伴的ObjC或者Java/JNI代码的临界点。 此处我们用了一个办法,就是把HashMap这个只存在于Rust侧的collections类型(就像Java里的collectionclasses只存在于Java一样),包装在一个类似C++的smartpointer这样的Box里,返回这一整个数据结构在内存里的地址
至此,我们的工作基本上完成90%,是不是很简单?
把提供“花名册”的函数暴露给其他语言使用到这一步为止,我们都是在Rust世界中折腾。 但是最终这些成果必须被外界发现和使用。 最后异步,就是把“花名册”送到异构语言的世界中,我们需要利用RustFFI(ForeignFunctionInterface)去让Rust编译器编译上述代码时,生成C风格的代码库,所以对上述函数还要做一点补充:
#[no_mangle]pub?unsafe?extern?C?fn?myext_register_apis()?->?*mut?HashMapno_mangle告诉Rust编译器,编译时不要混淆或改变myplugin_register_api()这个函数名字,否则ObjC或者Java/JNI侧就无法知道用什么名字调用了。
注意上述函数的声明里,有unsafe和externC的标识,extern好理解,就是标识这个函数是供异构语言以C函数调用的方式使用,unsafe涉及Rust关于什么才是内存安全、线程安全的规则或者说思想,详情读者可自行了解。 在此,主要是我们用到了Box::into_raw这个函数,即我们把一个只在Rust里面才能解析的数据结构,通过一个原始指针把它丢到C侧了,相当于这一片内存被异构语言下的代码“持有”,其内存安全不再受Rust的监控和保障,所以是不安全的。
这里有一个问题,就是:既然Rust侧的HashMap无法被C侧解析,把这玩意儿的原始指针丢过去有什么用呢?有用,因为它实际上相当于一个不透明指针,是一个由宿主应用侧“持有”的handle,当宿主需要调用Rust的函数时,把这个handle传回来就是了。
有去有回,记得防止内存泄漏在RustFFI,每一次产生的into_raw操作,最终都必须有一次对应的from_raw操作。 前者把一片Rust管理的内存的控制权转移出去了,后者是外部的异构语言下的代码必须把该内存的控制权还给Rust,否则内存泄漏就发生了。 所以,最后我们还需要增加一个函数,供异构语言在使用完上面的东西后,记得通知Rust回收:
#[no_mangle]pub?unsafe?extern?C?fn?myext_release(ptr:?*mut?HashMap注意,调用这个函数是宿主应用开发者的责任,所以必须在你的plugin的使用说明文档中向他们强调。 这个比较丑陋但似乎没有什么好办法,跨语言的调用总是有一些小不便。
Re-cap:用Rust开发一个FinClipSDK扩展的步骤实际上是非常简单和自由的,没有什么特殊库或者协议需要去继承实现,就是“徒手”写一个Rustlib,只要它包含以下要素:
准备提供给FinClip小程序调用的函数,以JSON字符串为入参和出参。 函数遵循fn(&String)->String的签名。 这些函数多少个都行,叫什么名字也无妨,自由选择
给上面这些函数造一个“花名册”,花名册的数据结构必须是以HashMap去存储“名字”->“函数指针”的映射关系,其中“名字”是你打算让外面的世界知道和使用的函数名(字符串),函数指针则是指向上述函数签名的类型
产生“花名册”的函数,需要使用RustFFI,也就是标记no_mangle,以及声明为unsafe。 “花名册”的数据结构(HashMap),包在一个不透明指针(opaquepointer)里,丢出去给异构语言代码(也就是准备使用这个plugin的宿主)持有备用。 这个返回“花名册”的函数,名字叫什么也无法,你只需要在自己的说明文档里注明(说明文档你总得有吧?)
提供一个释放“花名册”数据结构内存的函数,同样的,函数名字随意,告诉宿主开发者是什么即可
交付物是一个静态库正如《FinClip小程序+Rust》这个系列里所介绍过,Rust代码需要进行跨平台编译,构建出aarch64-apple-ios、x86_64-apple-ios以及Android相关的目标架构下的二进制库。例如生成适合在iossimulator和ios设备上运行的universallibrary:
cbindgen?src/?-l?c?>??lipo?--release最终你交付给宿主应用开发者的内容应该包括:
一个libmyplugin.a文件、一个myplugin.h的头文件
一个使用说明,包括:
如何获得你所提供的API的花名录,例如你提供了一个函数myplugin_register_apis
如何通知你释放花名录内存,例如你提供了一个函数myplugin_release
你的API花名录中,每一个API的“花名”,以及该API期望的JSON入参,返回的JSON出参
至此,作为一个Rust开发者提供FinClipSDKExtension的使命完成。 再次明确,myplugin的头文件名字、创建花名录数据结构和释放花名录内存的函数名字,都是开发者自由决定。
App开发者:如何使用Rust的插件接下来,就轮到宿主应用的开发者怎么使用了。 宿主应用,就是运行在iOS、Android或者其他设备端的应用软件,它嵌入了FinClipSDK从而获得运行小程序能力。
编写代码仅需加三行集成FinClipSDK详见官网,《FinClip小程序+Rust》也有介绍,不在此赘述。以下以iOSApp的集成上述myplugin为例,在AppDelegate.m增加三行代码(下面有注解的三行):
[package]name?=?mypluginversion?=?0.1.0edition?=?2021[lib]name?=?myplugin#?this?is?needed?to?build?for?iOS?and?-type?=?[staticlib,?lib][dependencies]serde_json?=?1.0.81??#?建议使用这个crate实现json对象序列化#?其他你准备封装或者依赖的crate0上面的代码,AppDelegate.m,在用xcode创建ObjC项目时自动生成,我们在这里初始化了FinClipSDK(详情见官网,或《FinClip小程序+Rust》系列。在此基础上,再安装myplugin,代码非常简单:
引用myplugin.h
调用FinClipExt的installFor方法,入参为初始化的FinClipSDKhandle,以及myplugin的API“花名录”对象(由myplugin_register_apis产生)
在宿主应用的生命周期中,找合适的阶段(例如应用退出)释放“花名录”内存(由myplugin_release提供)
这里的FinClipExt,负责了把RustAPI转换成ObjC方法再注入到FinClipSDK中。
编译构建需要链接静态库myplugin这个库,从上面我们已经可以看到,没有使用任何与FinClip直接相关的特殊的库,唯一的约束,就是两个规范:
自定义一个叫FinClipCall的函数指针类型,函数签名必须是fn(&String)->String
提供一个函数,能生成你计划提供给FinClip小程序开发者使用的自定义API的“花名录”,它的数据结构,必须是HashMap
仅此而已。 那么这个库是怎么被注入到FinClipSDK并能被小程序调用的呢?魔术在于,宿主App的开发者,在其项目中引入一个叫libfincliprust.a的静态库(这个库目前尚不是FinClip官方支持的标准工具,只是我个人的项目,且目前仅提供iOS版本。 有兴趣的朋友可以去优化,欢迎提供Android的版本,源代码在GitHub上,由ObjC和Rust代码组成)。 作为使用者,无需关注其中的实现,只要下载这个静态库,编译构建App的时候指定依赖与链接它即可。
最后,当然也必须把所要安装的myplugin的静态库,libmyplugin.a,引入项目,一同构建。
作为宿主应用开发者,引入一个叫myplugin的FinClipSDKExtension供FinClip小程序开发者调用的使命,也完成了。
小程序开发者:如何调用Rust接口上述myplugin的“花名录”里,有两个暴露给小程序的API,分别是api_drinker和api_whisky。 这两个用Rust写出来的、以JSON字符串为入参和出参的函数,经过libfincliprust.a的一些“魔术”操作,被转换成ObjC的method,并被动态注入到FinClipSDK中。 要使用这些API,FinClip小程序开发者需要在自己的小程序项目根目录下编写一个:
[package]name?=?mypluginversion?=?0.1.0edition?=?2021[lib]name?=?myplugin#?this?is?needed?to?build?for?iOS?and?-type?=?[staticlib,?lib][dependencies]serde_json?=?1.0.81??#?建议使用这个crate实现json对象序列化#?其他你准备封装或者依赖的crate1此后,在JavaScript中对这些API的调用,只需要通过ft对象即可进行,例如_drinker。
总结在一个现代的软件项目中,多语言混合编程是难以避免的-不同的语言在端到端技术链路上适合于解决不同环节的问题,但是也难免导致集成、融合的麻烦,往往是影响开发效率、引起诸多麻烦的。 例如跨语言的转接,涉及API接口的产生和数据结构在异构语言中反反复复的“翻译”,写gluecode非常繁琐。 FinClip更平滑的解决了前端的异构技术对接问题,在本文中,进一步介绍了一个较为“透明”的方法,让完全不熟悉JavaScript、不懂ObjC、不了解终端开发的工程师,能通过Rust这种强大的语言开发出逻辑通用的FinClipSDK扩展,最终供小程序开发者使用。
本文的示范代码在?。
原文:
C语言中,字符串格式化效率对嵌入式项目至关重要,特别是在处理大量日志信息时。 尽管 sprintf 传统上被用于此,但在性能敏感的场景下,可能需要寻找优化策略。 本文将探讨提升数字格式化到字符串效率的方法。 首先,最基础的格式化方法虽然快捷,但在百万次以上操作时,效率差距明显。 例如,将 long 型数字手动格式化为字符串,相比系统自带的函数,速度大约慢3倍。 尽管测试结果可能因环境而异,但差距是显著的。 测试2中,混合格式化字符串和数字时,虽然使用自定义函数 Long2String 更节省时间,但它的局限在于只能处理数字。 当需要同时处理数字和字符串时,sprintf 的灵活性使其更高效。 sprintf 的底层机制利用可变参数,通过 va_list、va_start、va_arg 和 va_end 等宏定义实现。 通过理解这个机制,我们可以优化代码,减少不必要的内存操作,从而提高执行速度。 总的来说,虽然自定义函数在某些特定情况下表现优秀,但对于通用格式化需求,利用 sprintf 或其优化版本能提供更好的性能。 对于C语言开发者来说,理解这些细节并根据项目需求选择合适的工具是提升效率的关键。
内容声明:
1、本站收录的内容来源于大数据收集,版权归原网站所有!
2、本站收录的内容若侵害到您的利益,请联系我们进行删除处理!
3、本站不接受违法信息,如您发现违法内容,请联系我们进行举报处理!
4、本文地址:http://www.jujiwang.com/article/ae82b7e5aa3d5a8a96fb.html,复制请保留版权链接!
窗口失踪之谜您是否遇到过这样的情况,正在使用计算机时,某个窗口突然消失无踪,您四处寻找,但它就是找不到了,这种现象称为窗口失踪,可能是由多种因素造成的,其中之一就是桌面云,什么是桌面云,桌面云是一种云计算服务,它将虚拟桌面环境,VDI,交付给用户,也就是说,您的桌面和应用程序不再存储在本地计算机上,而是存储在远程服务器中,用户可以通过...。
本站公告 2024-09-28 07:55:29
引言在当今信息时代,访问和管理数据变得至关重要,Web门户可以提供一个一站式的平台,用于轻松检索和操作数据,通过结合ASP,ActiveServerPages,和Access数据库,我们可以构建功能强大的Web门户,简化数据管理并提高效率,ASP的概述ASP是一种服务器端脚本语言,允许开发人员创建动态Web页面,它可以让Web页面与用...。
最新资讯 2024-09-27 18:44:19
引言Java运行时环境,JRE,是Java开发和部署环境的核心组件,它提供了一个可执行Java程序并使其与底层操作系统交互的平台,本文深入探讨JRE的架构、组件和功能,揭示其在Java生态系统中的关键作用,JRE的组件JRE由以下主要组件组成,Java虚拟机,JVM,负责执行Java字节码并管理Java程序的内存和资源,类库,包含供...。
技术教程 2024-09-27 17:56:40
NumPy是Python中用于科学计算的强大库,它提供了强大的多维数组对象,可以轻松地存储和处理大量数据,NumPy数组概述NumPy数组是一个固定长度、同种数据类型的数据集合,它可以用以下方式创建,importnumpyasnp从列表创建数组my,array=np.array,[1,2,3,4,5],从范围创建数组my,array=...。
本站公告 2024-09-24 21:51:11
如果您正在寻找一种方法来提升您的电影剪辑技能,那么Movieclip正是您所需要的,Movieclip是一款功能强大的电影剪辑软件,它提供了广泛的功能,可帮助您创建专业的视频,如果您是电影剪辑的新手或经验丰富的专业人士,Movieclip都能提供适合您的东西,Movieclip的主要功能可调节的时间线,可轻松编辑视频剪辑广泛的效果和过...。
技术教程 2024-09-24 08:10:50
气候变化的现实气候变化已经成为我们时代最严峻的挑战之一,由于人类活动释放的温室气体,地球的大气层正在变暖,导致极端天气事件、海平面上升和生物多样性丧失等一系列毁灭性影响,这些变化对地球上的每一个生态系统都产生了深远的影响,从北极的冰盖融化到热带雨林的干旱,气候变化正在对生态系统的结构和功能造成不可逆转的改变,气候变化对生态系统的影响以...。
本站公告 2024-09-15 21:23:19
量交付的方式,他们能够更灵活地响应客户需求并交付高质量的产品,结论Scrum是一个强大的敏捷框架,它可以通过协作、透明度和适应性帮助团队有效地开发产品,通过遵循本指南中概述的步骤和最佳实践,初学者可以有效地从头开始掌握Scrum,...。
互联网资讯 2024-09-13 10:43:08
简介随着应用程序变得越来越复杂,性能优化变得至关重要,PHP提供了一系列策略和技术,可以帮助您优化应用程序的效率并改善用户体验,本文将深入探讨PHP中的性能优化,并提供分步指南,帮助您实施这些策略,性能优化策略1.缓存缓存是在内存中存储数据的过程,以便可以快速检索,在PHP中,可以通过使用memcached、Redis等缓存系统来实现...。
最新资讯 2024-09-12 22:06:10
引言JavaWeb服务是基于HTTP协议的分布式计算技术,它允许应用程序跨平台、跨语言和跨网络进行通信,本文将深入剖析JavaWeb服务技术,涵盖其构建、部署和最佳实践,构建Web服务服务端编写服务接口服务接口定义了Web服务提供的操作,它是一个Java接口,扩展了`javax.jws.WebService`注解,并包含操作方法,``...。
本站公告 2024-09-12 15:42:53
简介云数据库备份是确保云数据库数据安全和可用性的重要方面,传统的备份方法可能会很复杂、耗时且成本高昂,利用云功能,我们可以简化和优化云数据库备份,从而降低成本、提高效率并改善数据保护,本文将重点介绍如何使用云功能将云数据库备份到本地,从而获得这些优势,云功能的好处自动化,云功能使备份过程自动化,从而减少了手动工作并提高了可靠性,按需定...。
最新资讯 2024-09-12 09:30:43
JavaScript是一种功能强大的编程语言,可用于创建动态和交互式的网页,它提供各种方法来处理日期和时间信息,包括获取当前月份,使用Date对象获取当前月份的最常用方法是使用Date对象,constdate=newDate,console.log,date.getMonth,输出当前月份,0,11,getMonth,...。
互联网资讯 2024-09-10 09:01:14
编程是一种让计算机按照指令执行特定任务的过程,它是一种强大的工具,可以用来解决问题、自动化任务、创建应用程序等等,为什么学习编程,学习编程有很多好处,包括,解决问题的能力提高,编程需要分析问题并将其分解成可管理的部分,从而提高你的解决问题能力,自动化任务,编程可以让你编写脚本和程序来自动化重复的任务,节省时间和精力,创建应用程序,你可...。
技术教程 2024-09-08 13:02:17