私はRust bindingsを、組み込みのコンストラクタとデストラクタを使用するCライブラリ用に書いています。 Cヘッダの生さびコード:メモリーから漏れなくCからRust構造体とメソッドをVecとして実装する方法は?
// Opaque structures transform to enumerate
pub enum UdbEntity_ {}
pub enum UdbReference_ {}
...
pub type UdbEntity = *mut UdbEntity_;
pub type UdbReference = *mut UdbReference_;
...
// Return a non-allocated, permanent list of all entities. This list may be
// used in places where an allocated entity list is required and may be
// safely passed to udbListEntityFree().
pub fn udbListEntity(list: *mut *mut UdbEntity, items: *mut c_int);
// Free an allocated list of entities.
pub fn udbListEntityFree(list: *mut UdbEntity);
...
// Return an allocated list of all references for entity.
// Free the list with udbListReferenceFree().
pub fn udbListReference(entity : UdbEntity,
refs : *mut *mut UdbReference,
items : *mut c_int);
// Free the allocated references list.
pub fn udbListReferenceFree(refs: *mut UdbReference);
これはgit2-rsのように安全なさびコードの実装である:
/// Structure of Entity.
pub struct Entity<'ents> {
raw: UdbEntity,
_marker: PhantomData<&'ents UdbEntity>,
}
/// Opaque structure of list of entities.
pub struct ListEntity<'db> {
raw: *mut UdbEntity,
len: usize,
_marker: PhantomData<&'db Db>,
}
/// An iterator over the Entity in list of entities.
pub struct EntityIter<'ents> {
range: Range<usize>,
ents: &'ents ListEntity<'ents>,
}
impl<'db> Drop for ListEntity<'db> {
fn drop(&mut self) {
unsafe { udbListEntityFree(self.raw) };
}
}
すぎるListReference
とReference
ため。
Vec<Entity>
(イテレータ、ソート用のスライスなど)と同じようにListEntity
と一緒に作業する必要がありますが、実装できません。実装の私のバージョンでは、私はスライスを作成することはできません:from_raw_parts
はUdbEntity
以上のスライスを返しますが、Entity
ではありません。
私はEntityList
でVec<Entity>
を維持し、私は(それを動かす)Vec<Entity>
を編集するときに、後で、EntityList
が低下し、割り当てられたリスト*mut UdbEntity
を解放しています。私も正しい生涯が必要です。
純粋な錆のコードを書き込むためにいくつかのシンプルな構造体(たとえばKind
、ListKind
)を逆にしましたが、もっと慣用的なパスが存在すると思います。
私は最初のバージョンが好きだったので、私は試していません。 2番目のバージョンはどうでしょうか?もしVecがListEntityによって所有されていれば、Vecの修正はListEntityの削除を引き起こします。 –
saruman9
@ saruman9 'Vec'が' ListEntity'によって所有されていて参照によって外部に見える場合、 'Vec'はそれを失うことはできません - それはRustによって保証されています。 'Vec'を変更可能にする必要があるなら、むしろそれを使うのではなく、' ListEntity'自体に必要な特性を実装してください。ここでの問題は、 'Vec'とその基礎構造を同期して変更する必要があることです。これは非常に困難です。 – Malcolm
私は配列 'UdbEntity'から' Entity'への 'Deref'特性の変換を実装しています(' FantomData'を使って、一部のFFI関数ではEntityを簡単に参照するのが難しいので)。 'ListEntity'ではこれが今動作します。私は 'ListReference'も実装しようとします。 – saruman9