C # для взаимодействия неуправляемых структур данных DLL - PullRequest
2 голосов
/ 18 мая 2010

У меня есть неуправляемая DLL, которая предоставляет функцию, которая принимает указатель на структуру данных. У меня есть код C #, который создает структуру данных и вызывает функцию DLL без каких-либо проблем. В точке вызова функции к dll указатель верный.

Моя проблема заключается в том, что DLL сохраняет указатель на структуру и использует указатель на структуру данных в более поздний момент времени. Когда библиотека DLL использует указатель, она становится недействительной (я предполагаю, что среда выполнения .net переместила память куда-то еще).

Каковы возможные решения этой проблемы?

Возможные решения, которые я могу придумать:

  • Исправить расположение памяти в структуре данных как-нибудь? Я не знаю, как бы вы сделали это в C # или даже если бы вы могли.
  • Выделите память вручную, чтобы я мог контролировать ее, например, используя Marshal.AllocHGlobal
  • Измените контракт функции DLL, чтобы скопировать структурные данные (это то, что я сейчас делаю, как краткосрочное изменение, но я вообще не хочу менять dll, если могу помочь, поскольку это не мой код для начала).

Есть ли другие лучшие решения?

Ответы [ 5 ]

2 голосов
/ 18 мая 2010

Вы можете выделить структуру, используя AllocHGlobal , которая помещает ее в неуправляемую память, где ГХ не перемещает и не освобождает ее. Вы также можете использовать вспомогательный класс, такой как this , чтобы GC закреплял память, поэтому он не будет перемещен или освобожден до тех пор, пока не будет закреплен.

1 голос
/ 18 мая 2010
1 голос
/ 18 мая 2010
  • Выделите память вручную, чтобы я мог контролировать ее, например, используя Marshal.AllocHGlobal

Довольно близко.

В этом конкретном случае я бы P / Invoke LocalAlloc выделил блок памяти и использовал StructureToPtr для его инициализации.

ОБНОВЛЕНИЕ: Поскольку вы можете редактировать DLL, я бы изменил DLL, чтобы обеспечить функции AllocXXX и FreeXXX.

0 голосов
/ 19 мая 2010

Класс GCHandle был разработан для обработки именно этого сценария. По сути, вы помещаете копию своей структуры в кучу, а затем вызываете GCHandle.Alloc с GCHandleType.Pinned. Когда DLL завершит работу со структурой, вызовите GCHandle.Free. Чтобы дать функции DLL адрес объекта, передайте его GCHandle.AddrOfPinnedObject. Пока он закреплен, GC не будет его перемещать.

0 голосов
/ 18 мая 2010

Не имея DLL, чтобы попробовать это, трудно сказать, сработает ли это. Я бы попробовал сделать объект «фиксированным» в вашем классе C #, чтобы память зависала на протяжении всего срока службы вашего приложения. Затем просто передайте статический объект в DLL.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...