Необходим не указатель на управляемый класс, а указатель на структуру неуправляемого кода, указатель которого я записываю в поле класса (управляемого), далее, я хочу перегрузить оператор &
для возможности извлечь адрес указателя, который записан в поле (не адрес управляемого класса). При этом для того что бы не было утечек памяти, и пользователи не могли изменять данное поле, которое нельзя изменять извне/внутри класса. Он должен быть единый на весь жизненный цикл класса.
Ничего не понимаю, если я перегрузил оператор &
в библиотеке c++-cli, то почему при попытке извлечь реальный адрес указателя, значение которого закрыто от внешнего доступа (нативного указателя void*
), c# мне вдруг говорит:
Не удается получить адрес, определить размер или объявить указатель на управляемый тип ("vlc_instance").
Пример класса:
public ref class SomePtr
{
private:
void* m_hide_ptr_;
SomePtr(): m_hide_ptr_(nullptr)
{
m_hide_ptr = get_native_ptr(); // Не указатель на управляемый объект!
}
// static // Оставим static на всякий, вдруг кто подумает что что-то не то
void*& operator &(const SomePtr^ value)
{
return value->m_hide_ptr_;
}
...
}
Неужели перегрузка оператора тут не поможет?
Нет, то, что вы хотите, невозможно.
Вы собираетесь вернуть ссылку на поле m_hide_ptr_
. Это поле, вместе со всем объектом, находится в управляемой куче, и, следовательно, может быть перемещено вместе с объектом. Хотя сборщик мусора при этом и обновляет управляемые ссылки, вашу неуправляемую ссылку он не обновит, поэтому взятие такой ссылки запрещено.
Без ссылки код компилируется:
static void* operator &(const SomePtr^ value)
{
return value->m_hide_ptr_;
}
(ну и ещё вам следует объявить его открытым, а то им никто не сможет воспользоваться).
Но при этом ваша цель — получить адрес поля/ссылку на поле — не достигается. Повторюсь, адрес переменной в управляемой куче вам взять не дадут, а если вы каким-то извращённым способом и исхитритесь, первый же пробег сборщика мусора превратит ваш указатель/ссылку в висящий.
На уровне C# вы не можете вызвать ваш перегруженный оператор &
потому, что с точки зрения C# перегружать унарный &
нельзя. Поэтому C# трактует &
как взятие адреса, а брать адрес управляемого объекта нельзя.
Вы можете, по идее, выкрутится, вызвав операцию напрямую:
SomePtr obj = new SomePtr();
unsafe
{
void* p = SomePtr.op_AddressOf(obj);
}
В этом случае, вероятно, имеет смысл назвать использовать обыкновенную функцию-член. Но это, снова-таки, для случая, если ваш оператор возвращает чистый указатель, а не ссылку.
Перегрузка операторов тут не нужна. Нужен, вероятно, pin_ptr
, в сочетании с Pinned GCHandle
(который позволяет предотвратить перемещение объекта сборщиком мусора). Для этого придется немного модифицировать класс:
#include <stdlib.h>
#include <stdio.h>
typedef void* LPVOID ;
using namespace System;
using namespace System::Runtime::InteropServices;
LPVOID get_native_ptr(){
return (LPVOID)& (L"Hello, C++/CLI world!\n");
}
[StructLayout(LayoutKind::Sequential)]
public ref class SomePtr
{
private:
LPVOID m_hide_ptr_;
GCHandle m_handle;
public:
SomePtr(): m_hide_ptr_(nullptr)
{
m_hide_ptr_ = get_native_ptr();
m_handle = GCHandle::Alloc(this,GCHandleType::Pinned);//закрепляем объект в памяти
}
IntPtr GetPtr() //получаем адрес m_hide_ptr_
{
pin_ptr<LPVOID> p = &m_hide_ptr_;
return (IntPtr)p;
}
//(добавить деструктор, освобождающий m_handle)
};
int main(array<System::String ^> ^args)
{
SomePtr ^ foo = gcnew SomePtr();
LPVOID* bar= (LPVOID*)(LPVOID)foo->GetPtr();//указатель на m_hide_ptr_
wprintf(L"%s",*(bar));//тестируем чтение
*bar = (LPVOID)& (L"Thanks, bye!\n");//тестируем запись
wprintf(L"%s",*bar);
system("PAUSE");
return 0;
}
Не знаю, имеет ли какой-то смысл данный код, но он работает.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Добрый деньПодскажите где поколдовать что бы заработал binding для контрола Picker? Вот XAML:
Задача сериализовать класс в json и передать его POST'ом на серверЯ написал код и он работает но у меня ощущение что я наделал много лишнего
Добрый деньПытаюсь распарсить XML в Visual Studio, но не получается сделать структуру как это сделано в XML
Нужно в приложении на c# получить ID только что обновлённой записи в MS Access, тк