LINUX.ORG.RU

загоны Сишечки и Раста с указателями

 , , ,


0

3

Есть либа net-snmp, есть что-то типа биндинга к расту. Окей, пробуем поюзать.
Есть функция
C:

extern oid *snmp_parse_oid(const char *, oid *, size_t *)

//

const char *_oid_str = "1.3.6.1.2.1.1.5.0";
oid _oid[MAX_OID_LEN];
size_t _oid_len = MAX_OID_LEN;

if (snmp_parse_oid(_oid_str, _oid, &_oid_len) != NULL) {
    // and so on...
}
Rust:
pub extern "C" fn snmp_parse_oid(arg1: *const raw::c_char, arg2: *mut oid, arg3: *mut libc::size_t) -> *mut oid

//

let oid_str = "1.3.6.1.2.1.1.5.0";
let mut _oid: Vec<oid> = vec![0; MAX_OID_LEN];
let mut _oid_len: size_t = MAX_OID_LEN;
let p_oid_len = &mut _oid_len as *mut size_t;

if snmp_parse_oid(oid_str.as_ptr() as *const c_char, _oid.as_mut_ptr(), p_oid_len) != null_mut() {
    // and so on...
}
Возвращает NULL (или null_mut() как у них там).
Скорее всего не так указатели передаю на буфер и его размер.
Где-то я видать не допонял этих извращений с владением.
При поиске какой-то инфы как работать с указателями в rust'е с С'шным кодом - всё в оф.доку сводится.
А там &a. Только вот нихрена это не *mut a. Про такие конструкции не могу инфу найти.
Может подскажете что?

★★

Строки в расте не нуль-терминированные. Или добавить \0 в конец oid_str, или использовать CString.

&mut T коэрсится в *mut T, так что p_oid_len можно убрать и писать &mut _oid_len прямо в вызове функции.

Вместо вектора можно использовать массив, как и в C: let mut _oid = [0 as oid; MAX_OID_LEN];

red75prim ★★★
()
Последнее исправление: red75prim (всего исправлений: 2)
Ответ на: комментарий от red75prim

Строки в расте не нуль-терминированные.

Точно! Я валенок, забыл про это, в этом косяк и был.

&mut T коэрсится в *mut T, так что p_oid_len можно убрать и писать &mut _oid_len прямо в вызове функции.

Да, так зашло.
Спасибо большое!

Получилось так, продолжу осваивать:

pub struct SNMPValue {
    _oid: Vec<u8>,
    data: Vec<u8>,
}

fn snmp_conv(_vars: *mut netsnmp_variable_list) -> SNMPValue {
    let mut value: SNMPValue = SNMPValue { _oid: vec![], data: vec![] };

    unsafe {
        if (*_vars)._type != SNMP_ENDOFMIBVIEW && (*_vars)._type != SNMP_NOSUCHOBJECT && (*_vars)._type != SNMP_NOSUCHINSTANCE {
            value._oid = vec![0; ((*_vars).name_length + 1) * 2];
            snprint_objid(value._oid.as_mut_ptr() as *mut c_char, value._oid.len(), (*_vars).name, (*_vars).name_length);
            if (*_vars)._type == ASN_OCTET_STR || (*_vars)._type == ASN_IPADDRESS {
                value.data = vec![0; (*_vars).val_len];
                memmove(value.data.as_mut_ptr() as *mut c_void, (*(*_vars).val.string()) as *const c_void, (*_vars).val_len);
            }
        }
    }
    return value;
}

fn snmp_get(snmp_sess: *mut netsnmp_session, _oid_str: &str) -> SNMPValue {
    let mut result: SNMPValue = SNMPValue { _oid: vec![], data: vec![] };
    let request: *mut netsnmp_pdu;
    let mut response: *mut netsnmp_pdu = null_mut();
    let status: raw::c_int;

    unsafe {
        let c_oid_str = CString::new(_oid_str).unwrap();
        let mut _oid: Vec<oid> = vec![0; MAX_OID_LEN];
        let mut _oid_len: size_t = MAX_OID_LEN;

        if snmp_parse_oid(c_oid_str.as_ptr(), _oid.as_mut_ptr(), &mut _oid_len) != null_mut() {
            request = snmp_pdu_create(SNMP_MSG_GET);
            snmp_add_null_var(request, _oid.as_ptr(), _oid_len);
            status = snmp_synch_response(snmp_sess, request, &mut response);
            if status == STAT_SUCCESS && response != null_mut() {
                if (*response).errstat == SNMP_ERR_NOERROR && (*response).variables != null_mut() {
                    result = snmp_conv((*response).variables);
                } else {
                    println!("SNMP: Failed to send SNMP_MSG_GET");
                }
                snmp_free_pdu(response);
            }
        }
    }
    return result;
}
goodwin ★★
() автор топика
Последнее исправление: goodwin (всего исправлений: 1)
Ответ на: комментарий от MKuznetsov

попытки писать на Rust системные вещи обречены

Вроде как да, либ мало, есть вроде возможность юзать либы С/С++.
Но на C (на чём изначально писал дискаверинг сети и инвентаризацию железок)
опять таки постоянно надо следить за всем, нигде ничего не забыть и не пальнуть в ногу.
На С++ переползать с современными его фичами и костылями... хз, не думаю что есть смысл.
На питоне можно, но будет не быстро, я уверен.
А вот rust как раз, и изучить, и всякие плюшки есть с типами, памятью.
На питон всегда переписать успею)))

По началу конечно разочаровало отсутствие многих вещей под rust.
Как будто все только и перекладывают json с одного api в другое по https... 🤦🏻‍♂️

goodwin ★★
() автор топика
Ответ на: комментарий от goodwin

Боже, как же это отвратно выглядит всё. Особенно вот эти вот _type, _oid, value._oid и прочий кал. Избавиться от этих мусорных подчёркиваний загромождающих синтаксис нельзя что ли?

EXL ★★★★★
()
Ответ на: комментарий от goodwin

Но на C

опять таки постоянно надо следить за всем, нигде ничего не забыть и не пальнуть в ногу.

На С++ переползать с современными его фичами и костылями… хз, не думаю что есть смысл.

как раз ради того, чтобы не палить по ногам и имеет смысл. Более того, изучение C++ как раз активно форсится тем же Страуструпом строго без изучения C, чтобы не привыкать к старому небезопасному пути, и как можно меньше палить в ноги.

seiken ★★★★★
()
Ответ на: комментарий от EXL

Можно конечно же. Я ж на скорую руку делал, чтобы проверить вообще что да как.
Я сам страдаю задротским вылизыванием кода. Глазкам должно быть приятно.

ps: но от венгерской нотации блевать тянет.

goodwin ★★
() автор топика
Ответ на: комментарий от seiken

Более того, изучение C++ как раз активно форсится тем же Страуструпом строго без изучения C, чтобы не привыкать к старому небезопасному пути, и как можно меньше палить в ноги.

А много он софта, решающего реальные задачи за последние лет 20 написал, чтобы знать где чаще всего палят в ноги?

snizovtsev ★★★★★
()
Ответ на: комментарий от snizovtsev

Чтобы знать «где чаще всего», своего собственного опыта недостаточно. Один может наступать на все грабли, даже самые тривиальные, а иной - только на самые сложные и скрытые. Нужна статистика.

seiken ★★★★★
()
Ответ на: комментарий от beastie

У вас там в вашей гошечке как с параметризованными типами? Всё так же гневно отрицают необходимость или начали чесаться?

WatchCat ★★★★★
()
Последнее исправление: WatchCat (всего исправлений: 1)
Ответ на: комментарий от seiken

ИМХО это не реально.

Нельзя давать шаблонные классы STL, до тех пор, пока человек не научится работать с памятью, понимать суть ООП, понимать внутренее устройство классов (конструкторы, деструктор, operator’ы и т.п.).

В противном случае мы получим Java-макак.

zx_gamer ★★
()
Ответ на: комментарий от seiken

А чем Си++ идиома отличается от Си?

В Си++ программист должен, используя функцию malloc (если потом потребуется realloc) или оператор new написать абстракцию для работы с памятью.

Примерами таких абстракций может послужить std::unique_ptr<T> (ранее std::auto_ptr<T>), std::vector<T> и другие реализации более сложных структур данных.

zx_gamer ★★
()
Последнее исправление: zx_gamer (всего исправлений: 1)