1

I'm trying to use the new vulkan API in my C# program. As we only have an access to the header file, I copied the code and I adapted it in an unsafe class to wrap it :

unsafe public static class Vk { ... public delegate void* PFN_vkAllocationFunction(...); public delegate void* PFN_vkReallocationFunction(...); public delegate void PFN_vkFreeFunction(...); public delegate void PFN_vkInternalAllocationNotification(...); public delegate void PFN_vkInternalFreeNotification(...); public struct AllocationCallbacks { void* pUserData; PFN_vkAllocationFunction pfnAllocation; PFN_vkReallocationFunction pfnReallocation; PFN_vkFreeFunction pfnFree; PFN_vkInternalAllocationNotification pfnInternalAllocation; PFN_vkInternalFreeNotification pfnInternalFree; } ... } 

All PFN_xxx was originally function pointers in the header, and I intuitively rewrote them as delegate. So, for the moment, it's working. However, late in the code, I have the following function, imported from the dll, which make an error :

[DllImport("Dll\vulkan-1.dll", EntryPoint = "VkCreateInstance")] public extern static Result CreateInstance( InstanceCreateInfo* pCreateInfo, AllocationCallbacks* pAllocator, <- error here Instance* pInstance); 

The error is the CS0208, described by the following message : "Cannot take the address of, get the size of, or declare a pointer to a managed type ('Vk.AllocationCallbacks')" By googling a little, I understood that AllocationCallbacks is managed, because of delegates in it. So how can I solve this problem ? I found no satisfying answers on the net, and I tried to marshal delegates in my struct as unmanaged function pointers (like this), but it seems to doesn't work, the compiler keep the error.

public struct AllocationCallbacks { void* pUserData; [MarshalAs(UnmanagedType.FunctionPtr)] PFN_vkAllocationFunction pfnAllocation; [MarshalAs(UnmanagedType.FunctionPtr)] PFN_vkReallocationFunction pfnReallocation; [MarshalAs(UnmanagedType.FunctionPtr)] PFN_vkFreeFunction pfnFree; [MarshalAs(UnmanagedType.FunctionPtr)] PFN_vkInternalAllocationNotification pfnInternalAllocation; [MarshalAs(UnmanagedType.FunctionPtr)] PFN_vkInternalFreeNotification pfnInternalFree; } 

Here is another problem : I have a struct in which fixed-size arrays of struct are defined. Original declaration was :

typedef struct VkPhysicalDeviceMemoryProperties { uint32_t memoryTypeCount; VkMemoryType memoryTypes[VK_MAX_MEMORY_TYPES]; uint32_t memoryHeapCount; VkMemoryHeap memoryHeaps[VK_MAX_MEMORY_HEAPS]; } VkPhysicalDeviceMemoryProperties; 

And I just translated in this way :

[StructLayout(LayoutKind.Sequential)] public struct PhysicalDeviceMemoryProperties { uint memoryTypeCount; [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_MEMORY_TYPES)] MemoryType[] memoryTypes; uint memoryHeapCount; [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_MEMORY_HEAPS)] MemoryHeap[] memoryHeaps; } 

But again, I have the same problem, the famous CS0208 error, because of the following function import :

[DllImport("Dll\vulkan-1.dll", EntryPoint = "VkGetPhysicalDeviceMemoryProperties")] public extern static void GetPhysicalDeviceMemoryProperties( PhysicalDevice physicalDevice, PhysicalDeviceMemoryProperties* pMemoryProperties); <-error here 

And this time, the error is because of fixed-size arrays. Any idea ?

Thank you for all your help !

6
  • 1
    Here's some info that could help when marshalling structs in C#. As for the callbacks, delegates are complex C# objects; they cannot be marshalled as simple C/C++ function pointers. Indeed, given that you're using C#, it'd probably be best to just pass NULL for the allocation callbacks. Just let the implementation allocate this stuff. Commented Mar 31, 2016 at 16:57
  • As Nicol said, passing in a null would probably be the best bet really. C# is managed and as far as I am aware, passing null into the allocationCallback just tells Vulkan to handle the memory management itself, which in a c# world would be what you would want anyway? I guess? Commented Apr 1, 2016 at 12:57
  • Thank you for your reply, @NicolBolas and Keithin8a. Indeed, I don't want to do my own memory management. So, I was able to solve the first problem, by replacing my delegates by a UIntPtr. No when I call my function, I simply send a "nullptr" as a parameter, to replace AllocationCallbacks pointer. However I didn't find any solution to solve the array's problem. Commented Apr 1, 2016 at 14:50
  • I've a question. Is transform my struct to a class and take a reference instance as a parameter going to solve my problem ? As only reference of classes are passed to a function, and not the instance itself, this maybe should work. I'll try. Commented Apr 1, 2016 at 15:05
  • A class is still a managed type, so it can have extra hidden members that the garbage collector uses. Passing that off to a C function which doesn't know about the extra members will not work well... Commented Apr 9, 2016 at 1:20

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.