Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.63/8: Рейтинг темы: голосов - 8, средняя оценка - 4.63
79 / 67 / 28
Регистрация: 22.04.2016
Сообщений: 384

Callback как член класса

02.09.2018, 16:21. Показов 1756. Ответов 2
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
В общем, захотел я немного поработать с библиотекой libgit2.
Эта библиотека предоставляет API Git'a. Т.е. можно написать свое приложение для каких-то определенных действий при работе с Git-репозиторием.
Поставил себе задачу: создать пустой репозиторий, добавить адрес удаленного репозитория и подключиться к нему.
Почитав документацию и немного погуглив, задача была решена:
Кликните здесь для просмотра всего текста

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#include "git2.h"
 
int my_git_cred_cb(git_cred** cred, const char* url, const char* username_from_url, unsigned int allowed_types, void* payload)
{
    if ((allowed_types & GIT_CREDTYPE_USERPASS_PLAINTEXT) != 0)
    {
        return git_cred_userpass_plaintext_new(cred, "user", "pass");
    }
    else
    {
        return -1;
    }
}
 
int main()
{
    const char *url = "https://user@bitbucket.org/user/repository.git"; // Адрес удаленного репозитория
    git_repository* repo = nullptr;
    git_repository_init(&repo, "/tmp/gitrep", false); // Указываем папку, где будет инициализирован пустой репозиторий
    
    git_remote* newremote = nullptr; 
    git_remote_create(&newremote, repo, "origin", url); // Добавляем к пустому репозиторию удаленный
 
    git_fetch_options opts = GIT_FETCH_OPTIONS_INIT;
    opts.callbacks.credentials = my_git_cred_cb; // Добавляем callback, который отвечает за данные пользователя, т.е. логин и пароль
    opts.callbacks.payload = nullptr; 
    git_remote_connect(newremote, GIT_DIRECTION_FETCH, &opts.callbacks, nullptr, nullptr); // Подключаемся к удаленному репозиторию
 
    return 0;
}

Все, вроде бы, хорошо, все работает. Но возникает недовольство callback'ом my_git_cred_cb, который пишеться по примеру git_cred_acquire_cb, т.е. должен иметь те же параметры и никак ему не передать user и pass, которые могут меняться и т.д. Глобальные переменные заводить не хочу.

Принял для себя решение, написать класс, который уберет все недостатки этого процедурного подхода.
Кликните здесь для просмотра всего текста

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class MyClass
{
public:
    MyClass(const std::string& url, const std::string& user, const std::string& pass)
    {
        git_repository_init(&m_Repo, "/tmp/gitrep", false); // Указываем папку, где будет инициализирован пустой репозиторий
        git_remote_create(&m_Newremote, m_Repo, "origin", url.data()); // Добавляем к пустому репозиторию удаленный
        m_User = user;
        m_Password = pass;
    }
 
    void connect()
    {
        git_fetch_options opts = GIT_FETCH_OPTIONS_INIT;
        opts.callbacks.credentials = my_git_cred_cb; // Добавляем callback, который отвечает за данные пользователя, т.е. логин и пароль
        opts.callbacks.payload = nullptr; 
        git_remote_connect(m_Newremote, GIT_DIRECTION_FETCH, &opts.callbacks, nullptr, nullptr); // Подключаемся к удаленному репозиторию
    }
 
private:
    int my_git_cred_cb(git_cred** cred, const char* url, const char* username_from_url, unsigned int allowed_types, void* payload)
    {
        if ((allowed_types & GIT_CREDTYPE_USERPASS_PLAINTEXT) != 0)
        {
            return git_cred_userpass_plaintext_new(cred, m_User.data(), m_Password.data());
        }
        else
        {
            return -1;
        }
    }
 
private:
    git_repository* m_Repo = nullptr;
    git_remote* m_Newremote = nullptr;
    std::string m_User;
    std::string m_Password;
};

Но сразу же получаю:
Code
1
Reference to non-static member function must be called
И ошибку при компиляции:
Code
1
cannot convert ‘MyClass::my_git_cred_cb’ from type ‘int (MyClass::)(git_cred**, const char*, const char*, unsigned int, void*)’ to type ‘git_cred_acquire_cb {aka int (*)(git_cred**, const char*, const char*, unsigned int, void*)}
Ок. Определяю метод my_git_cred_cb как static.
Предыдущая проблема исчезает, но появляется новая. В static-методе используются данные класса, которые не являются static.

Как выйти из этого замкнутого круга? Как решить данную проблему? Буду очень рад всем советам, ссылкам, рекомендациям.
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
02.09.2018, 16:21
Ответы с готовыми решениями:

Массив объектов класса как член другого класса
Здравствуйте. У меня тут возникла проблемка #include &quot;main.h&quot; class player { public: player(); player(char*); ...

Методы класса как callback функции
Всем привет. Пытаюсь разобраться как передавать методы класса в качестве callback. Я конечно понимаю, что есть решения вроде Boost или...

Член-ссылка на другой член класса
Есть класс Dot с двумя членами - x и y. Требуется еще один класс, который хранит width i height, но реализация этого класса ничем не...

2
Диванный эксперт
Эксперт С++
 Аватар для Max Dark
2550 / 2062 / 971
Регистрация: 09.10.2013
Сообщений: 4,793
Записей в блоге: 4
02.09.2018, 16:35
Лучший ответ Сообщение было отмечено igdev как решение

Решение

igdev, нужно передать в callback указатель на текущий объект.
В данном случае подходит параметр payload
C++
1
2
3
4
5
6
7
    void connect()
    {
        git_fetch_options opts = GIT_FETCH_OPTIONS_INIT;
        opts.callbacks.credentials = &MyClass::my_git_cred_cb
        opts.callbacks.payload = this; // <<<
        git_remote_connect(m_Newremote, GIT_DIRECTION_FETCH, &opts.callbacks, nullptr, nullptr); // Подключаемся к удаленному репозиторию
    }
далее в callback-функции преобразуем указатель к нужному типу и вызываем уже нестатическую функцию
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int MyClass::onGitCallBack(git_cred** cred, const char* url, const char* username_from_url, unsigned int allowed_types)
{
        if ((allowed_types & GIT_CREDTYPE_USERPASS_PLAINTEXT) != 0)
        {
            return git_cred_userpass_plaintext_new(cred, m_User.data(), m_Password.data());
        }
        else
        {
            return -1;
        }
}
static int MyClass::my_git_cred_cb(git_cred** cred, const char* url, const char* username_from_url, unsigned int allowed_types, void* payload)
{
    auto self = static_cast<MyClass*>(payload);
    return self->onGitCallBack(cred, url, username_from_url, allowed_types);
}
1
79 / 67 / 28
Регистрация: 22.04.2016
Сообщений: 384
02.09.2018, 17:00  [ТС]
Max Dark,

Не по теме:

Благодарю! Очень помогли! :)

0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
02.09.2018, 17:00
Помогаю со студенческими работами здесь

For_each и аргументы callback-функции; Как передать callback'у больше одного аргумента
Изучаю контейнеры и алгоритмы stl по Майерсу . С непривычки слегка охренел и запутался в них . В общем есть у меня простой вызов...

Шаблоны и функторы как callback для класса свойства объекта. Код работает - но не должен
Здравствуйте! Хочу написать реализацию класса свойства на шаблоне. Т.е есть объект, он инициирует необходимые проперти, в графическом...

Массив как член класса
Почему мне GCC выдаёт ошибку компиляции, что это zero-sized array ? struct Base { const char* d{&quot;f&quot;, &quot;f&quot;}; ...

Предикат как член класса
Напомните пожалуйста Reference to non-static member function must be called std::count_if (v.begin(), v.end(), func); // Reference to...

Vector как член класса
собственно заголовок моего класса: #pragma once #include &lt;Vector&gt; #include &quot;StdAfx.h&quot; #include &quot;PObject.h&quot; ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
3
Ответ Создать тему
Новые блоги и статьи
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
Расскажи мне о Мире, бродяга
kumehtar 12.11.2025
— Расскажи мне о Мире, бродяга, Ты же видел моря и метели. Как сменялись короны и стяги, Как эпохи стрелою летели. - Этот мир — это крылья и горы, Снег и пламя, любовь и тревоги, И бескрайние. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru