Закрепление экземпляра класса с помощью GCHandle.Alloc в C#

Я работаю с неуправляемой библиотекой C, в которой есть функция обратного вызова, которая вызывается из внутреннего потока в библиотеке C. Обратный вызов имеет параметр void * context.

Я хочу установить в этом контексте адрес экземпляра класса C#, чтобы я мог получить доступ к полям и свойствам членов из обратного вызова.

Я понимаю, что мне нужно закрепить память класса, чтобы гарантировать, что GC не перемещает его, поскольку код C примет копию адреса экземпляра. Однако GCHandle.Alloc () утверждает, что: «Экземпляр с непримитивными (непреобразуемыми) членами не может быть закреплен».

И, конечно же, достаточно кода, пытающегося закрепить класс или структуру, содержащую поле типа класса, не удается во время выполнения.

Как я могу передать адрес экземпляра класса C# в свой код C++ и убедиться, что адрес остается действительным (т. Е. Не перемещается GC)?

РЕДАКТИРОВАТЬ # 1 Исправление: это библиотека C, а не C++, как указывалось ранее (исправлено в тексте выше). Но это не должно иметь никакого значения.

Это прототип обратного вызова C:

void Callback(uint32_t hCamera, uint32_t dwInterruptMask, void *pvParams);

И завернутый в C#:

[UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
public unsafe delegate void PHX_AcquireCallBack(uint hCamera, uint dwInterruptMask, 
    IntPtr pvParams);

pvParams передается в библиотеку C при установке обратного вызова. Библиотека хранит указатель, но не пытается получить к нему доступ. Он просто передает его обратно всякий раз, когда вызывает обратный вызов.

При использовании библиотеки из кода C++ я обычно передаю указатель this на pvParams.

чтобы я мог получить доступ к полям участников - где? на стороне C++? это не имеет смысла ... на стороне C#? Тогда почему ты хочешь приколоть это?
Selvin 07.01.2019 16:10

Не могли бы вы поделиться с нами вызовом функции? Есть ли в этой библиотеке документация?

Martin Verjans 07.01.2019 16:17

Поскольку сторона C++ принимает копию адреса, я считаю, что экземпляр C# должен быть закреплен, чтобы гарантировать, что он не перемещается сборщиком мусора. Код C++ - мой; см. EDIT для получения дополнительной информации.

JPh 08.01.2019 10:28

вы можете использовать GCHandle.Alloc () в любом экземпляре класса с обычным типом дескриптора (не закрепленным)

Selvin 09.01.2019 23:15

@Selvin Верно, но я считаю, что мне нужно закрепить память, поскольку я передам адрес объекта в свою библиотеку C. Если вы думаете, что мне не нужно закреплять память, дайте мне знать, почему?

JPh 10.01.2019 12:32

потому что GCHandle будет иметь текущие адреса вашего объекта, даже если GC переместит его ... и вы передадите указатель GCHandle там, а не адрес вашего объекта ... см. пример ... TextWriter tw в этом примере будет вашим объектом контекста

Selvin 10.01.2019 12:33

в любом случае я бы изменил PHX_AcquireCallBack на статический ... и я бы использовал this из pvParams, как в примере

Selvin 10.01.2019 12:40
dotnetfiddle.net/ads8xY
Selvin 10.01.2019 12:55

Ваш пример работает (я думаю), потому что GCHandle находится в стеке и остается действительным до тех пор, пока обратный вызов не вернется. В моем случае «контекст» хранится в библиотеке C, и внутренний поток C вызывает обратный вызов. Поэтому мне пришлось бы сделать GCHandle членом моего класса или разместить его в куче. В любом случае GCHandle может быть перемещен сборщиком мусора, и, таким образом, указатель, удерживаемый C lib, будет недействительным. Или чего-то не хватает?

JPh 18.01.2019 12:18
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
9
267
0

Другие вопросы по теме