Problem marshalling with Unmanaged.LPUTF8Str #52810
-
I didn't want to file this as a bug because I think I'm causing the problem but I don't know why. I'm updating our Vulkan library P/Invokes and interop structures to .NET5 where we can use the The problem is though, that the method [DllImport(VulkanLibrary.Name)] static extern void vkGetPhysicalDeviceProperties(IntPtr physicalDevice, out VkPhysicalDeviceProperties properties); throws some memory exception with the struct given below. The docs explicitly say that it is a nul-terminated UTF8 string so I thought it should work. What does work is using [StructLayout(LayoutKind.Sequential)]
public readonly struct VkPhysicalDeviceProperties
{
public readonly VulkanVersion ApiVersion;
public readonly VulkanVersion DriverVersion;
public readonly int VendorId;
public readonly int DeviceId;
public readonly VkPhysicalDeviceType DeviceType;
// The docs say that it is an UTF8 (nul-terminated) string, the question is why LPUTF8Str doesn't work.
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaxPhysicalDeviceNameSize)]
public readonly string DeviceName;
public readonly Guid PipelineCacheUuid;
public readonly VkPhysicalDeviceLimits Limits;
public readonly VkPhysicalDeviceSparseProperties SparseProperties;
} |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
The difference between For the struct VkPhysicalDeviceProperties
{
VulkanVersion ApiVersion;
VulkanVersion DriverVersion;
int VendorId;
int DeviceId;
VkPhysicalDeviceType DeviceType;
char DeviceName[MaxPhysicalDeviceNameSize]; // Marshalled in-place in the structure
GUID PipelineCacheUuid;
VkPhysicalDeviceLimits Limits;
VkPhysicalDeviceSparseProperties SparseProperties;
}; For the LPUTF8Str case, the string is marshalled as a pointer to the allocated string, so the struct would look like the following: struct VkPhysicalDeviceProperties
{
VulkanVersion ApiVersion;
VulkanVersion DriverVersion;
int VendorId;
int DeviceId;
VkPhysicalDeviceType DeviceType;
char* DeviceName; // Marshalled as a pointer
GUID PipelineCacheUuid;
VkPhysicalDeviceLimits Limits;
VkPhysicalDeviceSparseProperties SparseProperties;
}; From what it sounds like, the ByValTStr case has the matching layout to the native code, which would be why it works and why the LPUTF8Str case does not. |
Beta Was this translation helpful? Give feedback.
The difference between
ByValTStr
andLPUTF8Str
is where the string is placed in memory.For the
ByValTStr
case, the native representation of theVkPhysicalDeviceProperties
struct would look like the following:For the LPUTF8Str case, the string is marshalled as a poin…