Разница между &IntPtr и .ToPointer() в небезопасном контексте – P/InvokeC#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Разница между &IntPtr и .ToPointer() в небезопасном контексте – P/Invoke

Сообщение Anonymous »

Я работаю с cuDNN и использую C# с P/Invoke для оболочки функций CUDA/CuDNN, что требует обработки указателей в небезопасном контексте. В частности, я реализую функцию для установки атрибутов дескрипторов серверной части cuDNN:

Код: Выделить всё

[LibraryImport("cudnn64_9.dll", EntryPoint = "cudnnBackendSetAttribute")]
private unsafe static partial int CudnnBackendSetAttribute(IntPtr descriptor, int attributeName, int attributeType, long elementCount, void* arrayOfElements);
public unsafe static void SetAttribute(IntPtr descriptor, CuDnnBackendAttribute attributeName, CuDnnBackendAttributeTyp attributeType, long elementCount, void* value)
{
CudaErrorHandler.ExecuteWithCudnnErrorHandling(() => CudnnBackendSetAttribute(descriptor, (int)attributeName, (int)attributeType, elementCount, value));
}
В некоторых частях моего кода мне нужно передать IntPtr в функцию SetAttribute в качестве указателя Descriptor_t. Я заметил, что использование &IntPtr работает отлично, но попытка использовать .ToPointer() приводит к исключению во время выполнения:

Код: Выделить всё

// Works fine
CudaDNN.SetAttribute(fpropDesc, CuDnnBackendAttribute.CUDNN_ATTR_OPERATION_CONVOLUTION_FORWARD_X, CuDnnBackendAttributeTyp.CUDNN_TYPE_BACKEND_DESCRIPTOR, 1, &xDesc);

// Causes runtime error
CudaDNN.SetAttribute(fpropDesc, CuDnnBackendAttribute.CUDNN_ATTR_OPERATION_CONVOLUTION_FORWARD_X, CuDnnBackendAttributeTyp.CUDNN_TYPE_BACKEND_DESCRIPTOR, 1, xDesc.ToPointer());
При использовании .ToPointer() возникает следующая ошибка:

Код: Выделить всё

System.Runtime.InteropServices.SEHException: "External component has thrown an exception."
Правильно ли я понимаю:
  • &IntPtr дает мне адрес IntPtr себя в управляемой памяти.
  • .ToPointer() предоставляет указатель, который обертывает IntPtr, указывая на
    фактический ресурс в неуправляемой памяти.

    Если я прав, что использование &IntPtr означает, что я передаю адрес управляемого объекта, то я не понимаю, почему библиотека cuDNN обрабатывает его правильно и без проблем интерпретирует . С другой стороны, использование .ToPointer() приводит к исключению, показанному выше.
    Мои вопросы:
  • Почему здесь работает использование &IntPtr, а .ToPointer() нет?
  • Может ли это быть связано с тем, как обрабатывается маршаллер P/Invoke или CLR
    Конкретно IntPtr?
  • Существует ли какой-то скрытый механизм, который делает &IntPtr подходящим
    для передачи в неуправляемый код, несмотря на то, что это управляемый адрес?
  • Есть ли какой-либо передовой опыт или более глубокое понимание того, почему
    IntPtr.ToPointer() может вызвать такую ​​проблему, особенно при работе
    в небезопасном контексте с внешними библиотеками, такими как cuDNN? >
Мне особенно интересно понять, почему &IntPtr работает нормально, несмотря на то, что указывает на управляемую память, и как CLR обеспечивает правильное поведение при взаимодействии с неуправляемым сервером.
Заранее спасибо!

Подробнее здесь: https://stackoverflow.com/questions/791 ... t-p-invoke
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C#»