Как я могу предоставить альтернативное определение внешней привязки FFI "C"?

Я использую стороннюю библиотеку, которая содержит привязку к функции extern "C":

extern "C" {
    pub fn PageAddItemExtended(
        page: Page,
        item: Item,
        size: Size,
        offsetNumber: OffsetNumber,
        flags: ::std::os::raw::c_int,
    ) -> OffsetNumber;
}

Item определяется как тип Pointer, который определяется как *mut ::std::os::raw::c_char. Эта конкретная функция никогда не изменяет данные, на которые указывает Item, поэтому я хотел бы предоставить ей неизменное значение.

Если бы у меня был контроль над сторонней библиотекой, я мог бы просто опустить mut из определения Item, и все было бы хорошо, но я этого не делаю.

Я попытался добавить второе определение этой функции extern "C" без mut, но это вызвало эту ошибку:

error[E0255]: the name `PageAddItemExtended` is defined multiple times
  --> src/segment/page.rs:49:5
   |
3  |   use crate::pg_sys::PageAddItemExtended;
   |       ---------------------------------- previous import of the value `PageAddItemExtended` here
...
49 | /     pub fn PageAddItemExtended(
50 | |         page: Page,
51 | |         item: *const ::std::os::raw::c_char,
52 | |         size: Size,
53 | |         offsetNumber: OffsetNumber,
54 | |         flags: ::std::os::raw::c_int,
55 | |     ) -> OffsetNumber;
   | |______________________^ `PageAddItemExtended` redefined here
   |
   = note: `PageAddItemExtended` must be defined only once in the value namespace of this module
help: you can use `as` to change the binding name of the import
   |
3  | use crate::pg_sys::PageAddItemExtended as OtherPageAddItemExtended;
   |   

Это имеет смысл; если мой код вызовет эту функцию, компилятор не будет знать, какое определение использовать.

Есть ли решение этой проблемы? Какой-то способ заставить компилятор использовать другое определение функции?

Не могли бы вы просто опустить use crate::pg_sys::PageAddItemExtended;?

Johannes 10.05.2022 17:58

@Johannes Спасибо, да, это компилируется. Не могу поверить, что я не подумал об этом. Сделайте ответ, и я приму его.

ccleve 10.05.2022 18:06
Эта конкретная функция никогда не изменяет данные, на которые указывает Item, поэтому я хотел бы предоставить ей неизменяемое значение. — Необработанные указатели *mut и *const в основном представляют собой причудливые линты, и вы можете свободно перемещаться между ними. Это только ссылки, где это имеет значение для Rust.
Shepmaster 10.05.2022 18:12

@Shepmaster Да, это тоже работает. let itemptr = value.as_ptr() as *mut _; Теперь мне вообще не нужно переопределять PageAddItemExtended. Спасибо.

ccleve 10.05.2022 18:23
Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
1
4
28
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как говорит компилятор, он терпит неудачу, потому что PageAddItemExtended уже определен. Опустите предыдущее определение use crate::pg_sys::PageAddItemExtended;, и оно будет успешно скомпилировано.

Другие вопросы по теме