Rust 如何在库中实现长寿命变量/状态?

Rust 如何在库中实现长寿命变量/状态?,rust,Rust,我知道在Rust中实现全局/实例/模块变量之类的东西的首选方法是在main()或其他公共入口点中创建所述变量,然后将其传递给需要它的人。 似乎还可以对不可变变量使用lazy_static,也可以将其与mutex组合以实现可变变量 在我的例子中,我使用Rust来创建一个。因此,通过绑定到Python,我需要在Rust库中存储大量可变状态(以响应Python应用程序调用的许多不同函数调用) 存储该状态的首选方式是什么 因为我没有main() 通常,如果没有其他要求,答案是将您的状态绑定到某个对象中,

我知道在Rust中实现全局/实例/模块变量之类的东西的首选方法是在
main()
或其他公共入口点中创建所述变量,然后将其传递给需要它的人。 似乎还可以对不可变变量使用
lazy_static
,也可以将其与
mutex
组合以实现可变变量

在我的例子中,我使用Rust来创建一个。因此,通过绑定到Python,我需要在Rust库中存储大量可变状态(以响应Python应用程序调用的许多不同函数调用)

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

因为我没有
main()
通常,如果没有其他要求,答案是将您的状态绑定到某个对象中,并将其交给客户机。一个流行的名称是
Context

然后,客户机必须在每个需要该对象的函数调用中传递该对象:

  • 或者将功能定义为对象上的方法
  • 或者要求对象作为函数/方法的参数
这将为客户提供完全控制权。

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

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


例外情况 有些情况下,例如缓存,功能不受影响,只影响性能


在这种情况下,虽然灵活性是可以理解的,但它可能比任何东西都更具负担。一个全局的,或者线程本地的,将是有意义的。

我很想在这里使用
不安全的
代码。您不能使用非静态生存期,因为您的状态的生存期将由Python代码决定,Rust看不到。另一方面,
静态
状态还有其他问题:

  • 它必须持续到程序结束,这意味着无法恢复不再使用的内存
  • 静态变量本质上是单例变量,因此很难编写一个对库进行多种独立使用的应用程序
我会使用类似的解决方案,但不是在接口上来回传递整个数据结构,而是在堆上不安全地分配它,然后来回传递某种句柄(即指针)

您可能希望编写一个清理函数,并记录您的库,以迫使用户在使用特定句柄时调用清理函数。实际上,您将数据生命周期的管理明确委托给调用代码

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


可能会有助手板条箱和库来帮助做这类事情。我对rust还不太熟悉。

可变状态的本质是什么,为什么它需要在函数调用中保持?状态将由许多结构向量存储,每个结构向量包含数千个元素,并且可能包含结构中的许多层次结构。它将是一个微型处理器的模型。它需要跨函数调用持久化,因为Rust用于主应用程序引擎,但通过Python接口向用户公开。单个Python进程将调用Rust函数来操作和查询模型,Rust域需要跟踪该状态。另请参阅。感谢@Shepmaster、user31601和Matthieu M。感谢您的时间和耐心。我花了一段时间,但我明白你们现在都在想什么,这是你们提供的一个很好的解决方案。一旦我得到了一个基于FFI示例的有效解决方案,我可能会用更通俗的语言来回答这个问题。再次感谢@user31601,请参见上文谢谢您的回答,我可以看到它可以用于一些简单的应用程序配置,事实上我已经为此做了一些工作。但是,在本例中,我们讨论的是大量数据,例如许多MB,我在Rust中专门为性能而做,我不想将其全部传递到Python空间。我希望它只存在于Rust中,并通过API将其暴露于Python中,以读取/写入其离散部分。也许我刚才添加到问题中的注释提供了更好的上下文。@Ginty:您不必向Python公开内部内容。从Python的角度来看,它可能只是一个状态块的不透明句柄(
void*
,用C语言来说),用户将其传递给函数调用。好的,谢谢你的澄清,但我认为它并没有真正回答我的问题。这似乎是“如何向客户机/Python公开生锈的数据”之类问题的答案,而我的问题是如何在生锈的一端存储数据。我不想将[多兆字节的数据]全部传递到Python空间-@Ginty没有理由这样做。Python C代码可以拥有该结构(或者将该结构放在
框中,它拥有该原始指针),然后将对该数据的引用传递回代码。传递8字节的指针并不困难。谢谢@Shepmaster