Kiwimanshare
Kiwimanshare

Reputation: 150

Difference between &IntPtr and .ToPointer() in an unsafe context - P/Invoke

I'm working with cuDNN and using C# with P/Invoke to wrap CUDA/CuDNN functions, which requires handling pointers in an unsafe context. Specifically, I'm implementing the function to set attributes of cuDNN backend descriptors:

[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));
}

In some of my code, I need to pass an IntPtr to the SetAttribute function as a Descriptor_t pointer. I noticed that using &IntPtr works perfectly fine, but trying to use .ToPointer() results in a runtime exception:

// 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());

The error I get when using .ToPointer() is:

System.Runtime.InteropServices.SEHException: "External component has thrown an exception."

Am I getting this right:

If I'm right, that using &IntPtr means I'm passing the address of a managed object, then I don't understand why the cuDNN library seems to handle it correctly and interprets it without problems. Using .ToPointer(), on the other hand, results in the exception shown above.

My Questions:

I am specifically interested in understanding why &IntPtr works fine despite pointing to managed memory, and how the CLR ensures the right behavior when interfacing with the unmanaged backend.

Thanks in advance!

Upvotes: 1

Views: 78

Answers (0)

Related Questions