Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.63/8: Рейтинг темы: голосов - 8, средняя оценка - 4.63
118 / 5 / 4
Регистрация: 05.05.2013
Сообщений: 334
1

Перевод указателя на член класса в обычный указатель

19.08.2019, 21:45. Показов 1671. Ответов 4
Метки нет (Все метки)

Добрый день.

Есть некоторый API, который принимает обычные указатели на функцию и поэтому при создании приложения на ООП возникает проблема перевода указателя на член класса в обычный указатель.

Например: у нас есть класс

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
#ifndef LIGHT_SOURCE_CORE_SYSTEM_CALLBACK_H
#define LIGHT_SOURCE_CORE_SYSTEM_CALLBACK_H
 
#include "thread.h"
 
namespace LightSource
{
    namespace Core
    {
        namespace System
        {
            class Callback
            {
            private:
                Thread* m_thread;
 
                int CallbackThread(unsigned int args, void *argp)
                {
                         /* выполнение кода в отдельно выделенном потоке будет тута */
                }
            public:
                Callback()
                {
                        m_thread = LightSource::Core::System::Thread::Create("update_thread", this->CallbackThread, 0x11, 0xFA0, 0, 0);
    
                        if (m_thread->IsValid())
                        {
                                m_thread->Start(0, 0);
                        }
                }
                
                virtual ~Callback();
            };
        }
    }
}
 
#endif
Проблема в том, что статичная функция Thead::Create вторым параметром принимает обычный указатель след. типа:

C++
1
typedef int (*SceKernelThreadEntry)(unsigned int args, void *argp);
Т.е. происходит ошибка, т.к. на вход я посылаю:
C++
1
int (LightSource::Core::System::Callback::*)(unsigned int, void*) // member pointer
В место:
C++
1
int (*)(unsigned int, void*) // ordinary pointer
Вопрос: можно перевести из указателя на член класса (pointer-to-member-function) в обычный указатель (pointer-to-function)?
0

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
19.08.2019, 21:45
Ответы с готовыми решениями:

Передача указателя на функцию-член
Всем привет ! Необходимо передать функцию-член в качестве параметра другой функции-члену....

Указатель на объект из указателя на член класса
Что как-то сей вопрос ставит меня в тупик. class A { int i; } obj; int main()

Не могу разобраться с синтаксисом указателя на указатель-член структуры
#include <iostream> int i = 100; struct str { int x; int *pi; } index, *p;

Определить обработчик исключений на преобразование указателя базового класса на указатель производного класса
Класс В является производным от класса А. Определить обработчик исключительной ситуации на...

4
6737 / 4537 / 1838
Регистрация: 07.05.2019
Сообщений: 13,725
Записей в блоге: 1
20.08.2019, 08:58 2
Лучший ответ Сообщение было отмечено darksector как решение

Решение

Цитата Сообщение от darksector Посмотреть сообщение
Вопрос: можно перевести из указателя на член класса (pointer-to-member-function) в обычный указатель (pointer-to-function)?
Ответ: нельзя и не нужно.
Я не очень понял назначение этих параметров (обычно достаточно void *), но обычно делается так:
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
class Callback
{
private:
    Thread* m_thread;
 
    int CallbackThread()
    {
        /* выполнение кода в отдельно выделенном потоке будет тута */
    }
 
    static int ThreadProc(unsigned int args, void *argp)
    {
        return static_cast<Callback *>(argp)->CallbackThread();
    }
 
public:
    Callback()
    {
        m_thread = LightSource::Core::System::Thread::Create("update_thread", &ThreadProc, 0x11, 0xFA0, 0, this);
 
        if (m_thread->IsValid())
        {
            m_thread->Start(0, 0);
        }
    }
 
    virtual ~Callback();
};
1
118 / 5 / 4
Регистрация: 05.05.2013
Сообщений: 334
20.08.2019, 11:26  [ТС] 3
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Я не очень понял назначение этих параметров (обычно достаточно void *), но обычно делается так:
Да, примерно так и думал... Надо тогда подумать немного над иной структурой.

PS: а никто не знает, SDK "неофициальный" (считаю что официальный, но слитый в сеть) и в нем не все дописано, даже доки.

Добавлено через 2 часа 5 минут
Нашел интересную статью. Оставлю ее здесь для общего понимания всем тем, кто будет попадать на эту тему:

Member Function Pointers and the Fastest Possible C++ Delegates
0
6737 / 4537 / 1838
Регистрация: 07.05.2019
Сообщений: 13,725
Записей в блоге: 1
20.08.2019, 11:31 4
Цитата Сообщение от darksector Посмотреть сообщение
Да, примерно так и думал... Надо тогда подумать немного над иной структурой.
А LightSource::Core::System::Thread это тоже твой класс?
0
118 / 5 / 4
Регистрация: 05.05.2013
Сообщений: 334
20.08.2019, 16:26  [ТС] 5
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
А LightSource::Core::System::Thread это тоже твой класс?
Конечно, это просто обертка... пока.

Пытаюсь отделить рабочее от нерабочего и определить некоторое взаимодействие компонентов внутри движка, чтобы разрабатывать игры было проще. Так же подвезти некоторую оптимизацию спец. под PSP.

Thread.h
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
39
40
41
42
43
#ifndef LIGHT_SOURCE_CORE_SYSTEM_THREAD_H
#define LIGHT_SOURCE_CORE_SYSTEM_THREAD_H
 
#include <pspthreadman.h>
 
namespace LightSource
{
    namespace Core
    {
        namespace System
        {
            class Thread
            {
            private:
                int m_threadId;
 
            public:
                Thread(int threadId);
                virtual ~Thread();
 
                bool IsValid() const;
 
                int GetThreadId() const;
                
                int Start(unsigned int arglen, void* argp);
 
                /**
                 * @brief Create a thread
                 * 
                 * @param name - An arbitrary thread name.
                 * @param entry - The thread function to run when started.
                 * @param initPriotity - The initial priority of the thread. Less if higher priority.
                 * @param stackSize - The size of the initial stack.
                 * @param attr - The thread attributes, zero or more of PspThreadAttributes.
                 * @param option - Additional options specified by SceKernelThreadOptParam.
                 * @return Thread* 
                 */
                static Thread* Create(const char* name, SceKernelThreadEntry entry, int initPriotity, int stackSize, unsigned int attr, SceKernelThreadOptParam* option);
            };
        }
    }
}
#endif
Thread.cpp
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
#include "thread.h"
 
LightSource::Core::System::Thread::Thread(int threadId)
{
    m_threadId = threadId;
}
 
LightSource::Core::System::Thread::~Thread()
{
}
 
bool LightSource::Core::System::Thread::IsValid() const
{
    return m_threadId >= 0;
}
 
int LightSource::Core::System::Thread::GetThreadId() const
{
    return m_threadId;
}
 
int LightSource::Core::System::Thread::Start(unsigned int arglen, void* argp)
{
    return sceKernelStartThread(m_threadId, arglen, argp);
}
 
LightSource::Core::System::Thread* LightSource::Core::System::Thread::Create(const char* name, SceKernelThreadEntry entry, int initPriotity, int stackSize, unsigned int attr, SceKernelThreadOptParam* option)
{
    return new LightSource::Core::System::Thread(sceKernelCreateThread(name, entry, initPriotity, stackSize, attr, option));
}
Пока делаю только предварительные наброски.

Добавлено через 3 часа 46 минут
Хм... только сейчас вспомнил, что на самом деле я уже что-то подобное делал примерно вот так:

AudioChannel.h
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
#ifndef AUDIO_CHANNEL_H
#define AUDIO_CHANNEL_H
 
#include <pspaudiolib.h>
#include <pspaudio.h>
 
#include "AudioFile.h"
#include "WavFile.h"
 
class AudioChannel
{
public:
    AudioChannel(unsigned short channel_id);
    ~AudioChannel();
 
    unsigned short getChannel();
    AudioFile* getAudioFile();
 
    void Play(const char* file);
    void Stop();
 
    bool isPlayed();
    bool isStoped();
 
    static void UnregisterAudioCallback(unsigned short channel);
 
private:
    unsigned short m_channel_id;
    AudioFile* m_audio_file;
};
 
void audioCallback_stereo(void* buff, unsigned int length, void* userdata); // <-- тоже самое но вынесено за класс
void audioCallback_mono(void* buff, unsigned int length, void* userdata); // <-- тоже самое но вынесено за класс
 
#endif
AudioChannel.cpp
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include "..\include\AudioChannel.h"
 
AudioChannel::AudioChannel(unsigned short channel_id)
{
    m_channel_id = channel_id;
    m_audio_file = new WavFile();
}
 
AudioChannel::~AudioChannel()
{
}
 
unsigned short AudioChannel::getChannel()
{
    return m_channel_id;
}
 
AudioFile* AudioChannel::getAudioFile()
{
    return m_audio_file;
}
 
void AudioChannel::Play(const char * file)
{
    if (!this->m_audio_file->isRunning() || this->isStoped()) {
        m_audio_file->setEnd(false);
        m_audio_file->fileOpen(file);
 
        if (m_audio_file->isRunning()) {
            if (m_audio_file->getNumChannels() == 1) pspAudioSetChannelCallback(m_channel_id, audioCallback_mono, this);
            else pspAudioSetChannelCallback(m_channel_id, audioCallback_stereo, this);
        }
    }
}
 
void AudioChannel::Stop()
{
    m_audio_file->End();
    m_audio_file->fileClose();
}
 
bool AudioChannel::isPlayed()
{
    return (m_audio_file->isRunning() && !m_audio_file->isEnded());
}
 
bool AudioChannel::isStoped()
{
    return (m_audio_file->isRunning() && m_audio_file->isEnded());
}
 
void AudioChannel::UnregisterAudioCallback(unsigned short channel)
{
    pspAudioSetChannelCallback(channel, 0, NULL);
}
 
void audioCallback_stereo(void* buff, unsigned int length, void* userdata)
{
    AudioChannel* audio_channel = (AudioChannel*)userdata;
 
    if (audio_channel->getAudioFile()->isRunning()) {
        audio_channel->getAudioFile()->readDataPCM();
 
        if (!audio_channel->getAudioFile()->isEnded()) {
            sample_stereo_t* ubuff = (sample_stereo_t*)buff;
            sample_stereo_t* u_dbuff = (sample_stereo_t*)audio_channel->getAudioFile()->m_data;
            unsigned int i;
 
            if (!audio_channel->getAudioFile()->isEnded()) {
                for (i = 0; i < length; i++) {
                    ubuff[i].l = u_dbuff[i].l;
                    ubuff[i].r = u_dbuff[i].r;
                }
            }
            else {
                AudioChannel::UnregisterAudioCallback(audio_channel->getChannel());
            }
        }
        else {
            AudioChannel::UnregisterAudioCallback(audio_channel->getChannel());
        }
    }
}
 
void audioCallback_mono(void* buff, unsigned int length, void* userdata)
{
    AudioChannel* audio_channel = (AudioChannel*)userdata;
    if (audio_channel->getAudioFile()->isRunning()) {
        audio_channel->getAudioFile()->readDataPCM();
 
        if (!audio_channel->getAudioFile()->isEnded()) {
            sample_stereo_t* ubuff = (sample_stereo_t*)buff;
            sample_mono_t* u_dbuff = (sample_mono_t*)audio_channel->getAudioFile()->m_data;
            unsigned int i;
 
            if (!audio_channel->getAudioFile()->isEnded()) {
                for (i = 0; i < length; i++) {
                    ubuff[i].l = u_dbuff[i].l_r;
                    ubuff[i].r = u_dbuff[i].l_r;
                }
            }
            else {
                AudioChannel::UnregisterAudioCallback(audio_channel->getChannel());
            }
        }
        else {
            AudioChannel::UnregisterAudioCallback(audio_channel->getChannel());
        }
    }
}
Т.е. просто вынес функции за класс...

Спасибо за помощь.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
20.08.2019, 16:26

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Передача указателя на функцию-член класса
Необходимо передать фунцию-член класса как аргумент в функцию другого класса. Код: Файл...

Хранение в map указателя на функцию-член шаблонного класса
Здравствуйте! Сделал я себе вызов написать джунгли из ООП деревьев, типо, объекты обмениваются...

Указатель на функцию-член класса
Нужно передать указатель на функцию класса A изнутри самого класса А в функцию, в качестве...

Указатель на функцию - член класса.
делаю так: class c1 { void foo(); } class c2 { void (*fp)();


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

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.