Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Problem marshalling with Unmanaged.LPUTF8Str #52810

Answered by jkoritzinsky
msedi asked this question in Q&A
Discussion options

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 Unmanaged.LPUTF8Str for marshalling UTF8 (nul-terminated) strings. So decided to go with this instead of marshalling as byte and then converting it to a C# string which makes our code more readable.

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 UnmanagedType.ByValTStr and I have no clue why.

 [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;
 }
You must be logged in to vote

The difference between ByValTStr and LPUTF8Str is where the string is placed in memory.

For the ByValTStr case, the native representation of the VkPhysicalDeviceProperties struct would look like the following:

 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 poin...

Replies: 1 comment 2 replies

Comment options

The difference between ByValTStr and LPUTF8Str is where the string is placed in memory.

For the ByValTStr case, the native representation of the VkPhysicalDeviceProperties struct would look like the following:

 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.

You must be logged in to vote
2 replies
Comment options

@jkoritzinsky: Thanks a lot for explaining this. For me it was not obvious from the docs.

Comment options

@jkoritzinsky: Bardzo dziękuję za wyjaśnienie. Dla mnie nie było to oczywiste w dokumentacji.

Answer selected by msedi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Q&A
Labels
None yet

AltStyle によって変換されたページ (->オリジナル) /