如何在库中实现长期存在的变量/状态?

时间:2019-11-25 09:38:43

标签: rust

我知道在Rust中实现诸如global / instance / module变量之类的首选方法是在main()或其他公共入口点中创建所述变量,然后将其传递给需要的人。 对于不可变变量,似乎也可以使用lazy_static,或者可以将其与mutex结合使用以实现可变变量。

就我而言,我正在使用Rust创建具有绑定到Python的.so,并且我需要在Rust库中存储大量可变状态(以响应Python应用程序调用的许多不同函数)

存储该状态的首选方式是什么?

是因为我没有lazy_static(或更笼统地说,在Python的函数调用之间不终止的任何函数),所以仅通过可变的main()方法实现它,还是有另一种方法来实现? ?

2 个答案:

答案 0 :(得分:6)

捆绑它

通常,在没有其他要求的情况下,答案是将您的状态捆绑在 some 对象中,然后将其移交给客户端。流行名称是Context

然后,客户端应该在每次需要它的函数调用中传递该对象:

  • 通过将功能定义为对象上的方法来实现。
  • 或者通过要求对象作为函数/方法的参数。

这将完全控制客户端。

客户端可能最终为其创建了一个全局变量,或者可能实际上欣赏能够处理多个实例的灵活性。

注:不需要提供对对象内部状态的任何访问;客户端所需的全部是一个句柄(在Python中为ref-counted),以控制生存期并决定何时使用哪个句柄。在C语言中,这将是void*


例外

在某些情况下,例如缓存,功能不会受到影响,而只会影响性能。

在这种情况下,尽管可以体会到灵活性,但它可能比任何东西都要负担更多。这样,全局或线程局部的方法就有意义了。

答案 1 :(得分:0)

我很想在这里加入unsafe代码。您不能使用非静态生存期,因为状态的生存期将由Python代码确定,Rust无法看到。另一方面,'static状态还有其他问题:

  • 它必须一直持续到程序结束,这意味着无法恢复不再使用的内存。
  • 'static变量本质上是单例,因此很难编写一个可以对库进行多次独立使用的应用程序。

我将采用类似于@Matthieu M. suggests的解决方案,但不是在接口上来回传递整个数据结构,而是不安全地在堆上分配它,然后传递某种句柄(即指针)。

您可能想编写一个清理函数,并记录您的库以强迫用户在使用特定句柄完成操作后调用清理函数。有效地,您将数据生命周期的管理明确委派给了调用代码。

如果需要,使用此模型,应用程序可以同时并独立地创建,使用和清除多个数据集(每个数据集均由其自己的句柄表示)。如果应用程序在完成时“忘记”清理句柄,则可能会发生内存泄漏,但这并不比将数据存储在'static变量中更糟。

可能会有辅助工具箱和库来协助执行此类操作。我对铁锈知之甚少。