What is needed is not a pointer to the managed class, but a pointer to the structure of the unmanaged code, the pointer of which I write in the class field (managed), then I want to reload the & operator to be able to extract the address of the pointer that is written in the field (not the managed class address). In this case, so that there would be no memory leaks, and users could not change this field, which can not be changed outside / inside the class. It should be one for the entire life cycle of the class.

I don’t understand anything, if I overloaded the & operator in the , then when trying to extract the real address of a pointer whose value is closed from external access (native pointer void* ) , suddenly tells me:

Cannot get address, determine size, or declare pointer to managed type ("vlc_instance").

Class example:

 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_; } ... } 

Doesn't operator overloading help here?

  • one
    When it comes to managed code, the garbage collector can move instances of classes back and forth. Therefore, the real address may change at any time. Therefore, it can not be obtained. In general, you need to look at the code: what exactly is done there. - Alexander Petrov
  • @AlexanderPetrov: I don’t think that GC has the right to move the structures created by unmanaged code to c . - LLENN
  • pointer to managed type ("vlc_instance") - Alexander Petrov
  • @AlexanderPetrov: an overloaded operator returns a pointer that lies in the class. At the same time it is impossible to make it open, or add methods to extract the pointer, which can serve as leaks. - LLENN
  • There is absolutely no point in getting an unmanaged pointer to a managed object, so this is forbidden. You can work with a managed object through a handle or pointers to the COM interfaces that it implements. If you need to know the real address of a class in memory, you probably need to take a pointer to one of its fields and dance from there, but not sure if it works. - MSDN.WhiteKnight

2 answers 2

No, what you want is impossible.

You are about to return a link to the m_hide_ptr_ field. This field, along with the entire object, is in a managed heap, and therefore can be moved along with the object. Although the garbage collector updates the managed links, it does not update your unmanaged link, so taking such a link is prohibited.

Without a link, the code compiles:

 static void* operator &(const SomePtr^ value) { return value->m_hide_ptr_; } 

(well, and you should also declare it open, otherwise nobody will be able to use it).

But while your goal - to get the address of the field / link to the field - is not achieved. I repeat, the address of the variable in the managed heap will not be given to you, and if you do something in a perverted way and fake it, the very first run of the garbage collector will turn your pointer / link into a hanging one.


At the C # level, you cannot call your overloaded operator & because from the point of view of C # you cannot overload unary & . Therefore, C # interprets & as taking the address, and you cannot take the address of the managed object.

You can, in theory, get out by calling the operation directly:

 SomePtr obj = new SomePtr(); unsafe { void* p = SomePtr.op_AddressOf(obj); } 

In this case, it probably makes sense to call using an ordinary member function. But this, again, for the case if your operator returns a clean pointer, not a link.

  • hmm, quite interesting, until I close the question, because it is still relevant. - LLENN

Operator overloading is not needed here. You probably need pin_ptr in combination with Pinned GCHandle (which helps prevent the garbage collector from moving the object). To do this, you will have to slightly modify the class:

 #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; } 

I don’t know if the code makes any sense, but it works.

  • You cannot do this: LPVOID* bar = (LPVOID*)(LPVOID)(foo->GetPtr()); . It is necessary to first save pin_ptr to a local variable, and then lead to a pointer. - Pavel Mayorov
  • But if you save pin_ptr to a local variable, then the address will be valid even after garbage collection! - Pavel Mayorov
  • @PavelMayorov the problem is that pin_ptr cannot be returned from a function (especially in C #, as Yami wants). Therefore, I say that it is necessary to strongly modify the code) - MSDN.WhiteKnight