drivers.cpp

  • tsettings::post_show()为什么要调用base_driver_.set_slot(null_str, nullptr)?——让refresh()可能会出现的卸载libroseaplt.so前,能安全调用“delete slot”,这个操作是要求libroseaplt.so还内存。

 

一、drivers.cpp

drivers.cpp实现了launcher管理驱动的主要操作。当中主要有三个类:trose_library、library、tdrivers。

  • trose_library。封装了加载、卸载某个小程序的libroseaplt.so。一个trose_library对应一个小程序。如果一个小程序正被多个驱动使用,系统也只有一个trose_library实例。
  • library。管理trose_library的std::shared_ptr智能指针。为防止不恰当使用trose_library造成内存泄漏,提供了library。caller应该使用library,尽量不要直接使用trose_library。一个小程序被多个驱动使用时,library的引用计数要大于1。
  • tdrivers。管理着系统正使用的所有驱动,整系统只有一个tdrivers实例。成员变量“std::map<int, library> libs”存储着各驱动对应的小程序,first是三种驱动类型:drivertype_base(0)、drivertype_laser(1)、drivertype_moveit(2),second是该类型驱动所在的小程序。

 

二、流程

[1/3]launcher启动时会调用tdrivers::init(...)

init两个任务。

  1. 让libs有3(drivertype_count)个library,虽然这时的library都是nullptr。有了这操作后,后绪可对libs安全使用[0]、[1]、[2]下标。
  2. 调用refresh。

[2/3]tdrivers::refresh(const std::vector<applet::tapplet>& applets)

refresh功能是根据正安装的小程序列表和preferences中存储的驱动、小程序关联关系,更新tdrivers中的libs。参数applets是系统中正安装的小程序列表。针对每种type

  1. 从preferences取出该type关联的小程序id,根据小程序id从applets找到小程序,记为applet。
  2. 在libs查找applet是否已被打开。1)如果没有打开,生成一个新的trose_library,覆盖掉libs[type].second。2)如果已打开,找到封装该trose_library的library,赋值给libs[type].second,实质就是引用计数加1。
  3. 调用check_and_correct。

[3/3]void tdrivers::check_and_correct(int type)

上面已针对type加载了对应的trose_library,记为rose_lib,check_and_correct检查这个rose_lib是否发生了意外。

  1. 调用rose_lib->opened()(不是打开,只是判断是否已打开),它可能返回失败。举个例子,新版本lib3rdparty.so修改了api参数。由于libroseaplt.so要调用lib3rdparty.so,如果它要使用的api中,新版lib3rdparty.so有的api参数发生改变,那不论windows还是android,SDL_LoadObject都是返回nullptr,即opened()返回false。对windows,还会弹出个需要手动点击“确定”才可以关闭的错误提示框。check_and_correct一旦查到这种意外,会弹出警告:选择了小程序“$drivervalue”作为$drivername,但不能打开“$libroseaplt” 。提示框关闭后,check_and_correct会取消该类型驱动关联该小程序。
  2. 虽然opened是true了,但该新版小程序可能已不再支持type对应的驱动。这有几种情况:1)新版小程序不再支持该驱动。2)新版本launcher修改了该类型驱动的C api参数。check_and_correct一旦查到这种意外,会弹出警告:选择了小程序“$drivervalue”作为$drivername,但该驱动没有实现方法:$absence。提示框关闭后,check_and_correct会取消该类型驱动关联该小程序。

 

三、设置界面切换驱动小程序,卸载小程序

3.1 设置界面切换驱动小程序

首要要知道,打开tsettings窗口,关闭tsettings窗口后,不管有没有切换驱动小程序,肯定会调用game.drivers().refresh()。如果切换过驱动小程序,那preferences会有变化,refresh()将按preferences更新驱动对应小程序。

实例:在设置窗口,将雷达驱动由Basic(studio)换为Basic。

  1. (tsettings::post_show)laser_driver_.set_slot(null_str, nullptr)。laser_driver_原先存的slot是Basic(studio)的tleagor_laser,要执行“delete slot”,这要求Basic(studio)的libroseaplt.so必须还在内存中。
  2. (tdrivers::refresh)加载Basic的libroseaplt.so,对应变量lib。
  3. (tdrivers::refresh)执行'hit_it->second = *lib'时,hit_it->second是Basic(studio)的,引用计数到0,导致卸载Basic(studio)的libroseaplt.so。这个“=”,接下还会加载Basic的libroseaplt.so。
  4. (game_instance::refresh_driver_slot)调用Basic的aplt_create_laser_slot创建tleagor_laser,并设为laser_driver的slot。

整个过程中,不论Basic(studio),还是Basic,都是系统中已安装的小程序。

第一步是省不掉的,因为要“delete slot”,必须要求在tdrivers::refresh之前执行。

 

3.2 卸载小程序

实例:卸载小程序Basic

  1. (trstore::tslot::uninstall_applet)调用game_instance::did_applet_will_uninstall。
  2. (did_applet_will_uninstall)发现雷达驱动用的是Basic,调用laser_driver_.set_slot(null_str, nullptr)。要执行'delete slot',这要求Basic的libroseaplt.so必须还在内存中。
  3. (trstore::tslot::uninstall_applet)调用tdrivers::did_uninstall。
  4. (tdrivers::did_uninstall)搜寻libs,找到雷达驱动用的是Basic,执行“it->second.reset(nullptr)”。因为没有驱动在用Basic了,引用计数到0,导致卸载Basic的libroseaplt.so
  5. (trstore::tslot::uninstall_applet)删除Basic小程序的res目录(preferences_aplt_path)。
  6. (trstore::tslot::uninstall_applet)删除Basic小程序的userdata目录。注:如果有同样studio版buhdleid的不删。

全部评论: 0

    写评论: