Можно ли, и как упаковать каким-то образом объект управляемый в указатель, и передать его в неуправляемый объект, что бы неуправляемый объект делал вызовы из этого указателя?
В большинстве случаев достаточно неуправляемого класса gcroot<...>
, который можно использовать вместо указателя. Считайте его разновидностью умного указателя.
В ситуации, когда нужен именно сырой указатель - можно использовать GCHandle.
Получение указателя:
GCHandle::ToIntPtr(GCHandle::Alloc(obj)).ToPointer()
Преобразование указателя обратно в объект:
GCHandle::FromIntPtr(gcnew IntPtr(ptr)).Target
Только не забудьте освободить GCHandle когда он перестанет быть нужен во избежание утечек памяти:
GCHandle::FromIntPtr(gcnew IntPtr(ptr)).Free()
Решил таким способом:
Добавил неуправляемый класс помощник, в котором есть map<int, gcroot<Object^>>
.
При записи в класс, сохраняем ссылку, и HashCode
класса. Далее извлекаем класс из неуправляемого метода/кода, и в качестве параметра в коллбэке передаем наш хэш код, за счет этого вызываем и извлекаем именно нужный класс.
Вызовы происходят на ура! А так же вместо System::Object^
может быть любой управляемый класс.
В итоге получаем такой класс:
#pragma once
#include <msclr\auto_gcroot.h>
#include <msclr\gcroot.h>
#include <vector>
#include <map>
using namespace msclr;
typedef std::map<int, gcroot<System::Object^>> mypack;
class vlc_helper
{
vlc_helper();
mypack m_map;
static vlc_helper* m_instance_;
public:
static vlc_helper& instance();
~vlc_helper();
void release();
gcroot<System::Object^> get_class(int id);
void remove_data(int id);
void add_data(int id, gcroot<System::Object^> ptr);
};
#include "stdafx.h"
#include "vlc_helper.h"
#include <iostream>
#include <iterator>
#include <cassert>
vlc_helper* vlc_helper::m_instance_ = nullptr;
vlc_helper::vlc_helper()
{
m_map = mypack();
}
vlc_helper::~vlc_helper()
{
m_map.clear();
}
vlc_helper &vlc_helper::instance()
{
if (!m_instance_)
{
m_instance_ = new vlc_helper();
}
return *m_instance_;
}
void vlc_helper::release()
{
delete m_instance_;
}
gcroot<System::Object^> vlc_helper::get_class(int id)
{
mypack::iterator data = m_map.find(id);
return data != m_map.end() ? data->second : nullptr;
}
void vlc_helper::remove_data(int id)
{
mypack::iterator data;
m_map.erase(id);
}
void vlc_helper::add_data(int id, gcroot<System::Object^> ptr)
{
m_map.insert(std::make_pair(id, ptr));
}
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Добрый деньУникален ли в рамках процесса дескриптор сокета (SOCKET), возвращаемый функциями создания сокета (socket(), accept())?
Смотрел документацию, но так и не нашел, как назначит к примеру QGamepad::buttonAChanged слушать свою собственную кнопку, которую мы назначили при старте...