Ich versuche, einen Vulkan-Wrapper in C# erstellen, aber ich habe einige Probleme, wenn ich eine Funktion aufrufen. Ich schrieb die vulkan.h Header wie folgt:C# DllImport: AccessViolationException beim Aufruf eines vkCreateInstance
public static class Vk {
[StructLayout(LayoutKind.Sequential)] public class Instance { }
public enum Result {
...
}
public enum StructureType {
...
}
[StructLayout(LayoutKind.Sequential)] public class ApplicationInfo {
public StructureType sType;
public IntPtr pNext;
public string pApplicationName;
public uint applicationVersion;
public string pEngineName;
public uint engineVersion;
public uint apiVersion;
}
[StructLayout(LayoutKind.Sequential)] public class InstanceCreateInfo {
public StructureType sType;
public IntPtr pNext;
public uint flags_VkInstanceCreateFlags;
public ApplicationInfo pApplicationInfo;
public uint enabledLayerCount;
public string[] ppEnabledLayerNames;
public uint enabledExtensionCount;
public string[] ppEnabledExtensionNames;
}
[DllImport("vulkan-1.dll", EntryPoint = "vkCreateInstance")]
public extern static Result CreateInstance(
InstanceCreateInfo pCreateInfo,
IntPtr AllocationCallbacks_pAllocator,
out IntPtr pInstance_Instance);
}
Die ursprüngliche Erklärung in C dieser Funktion
VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(
const VkInstanceCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkInstance* pInstance);
Nun ist, wenn ich meine Funktion aufrufen, ich bin wie dies zu tun:
Vk.InstanceCreateInfo instance_create_info = new Vk.InstanceCreateInfo();
...
IntPtr hinstance;
Vk.Result result = Vk.CreateInstance(instance_create_info, IntPtr.Zero, out hinstance); <-- error AccessViolationException
Ich verstehe nicht, wo ist mein Problem, denn es scheint eine gültige Lösung zu sein: StackOverflow : AccessViolationException when calling vkEnumeratePhysicalDevices via pInvoke from c#.
Ich habe versucht, durch meine Initialisierung IntPtr hInstance mit
Marshal.AllocHGlobal(Marshal.SizeOf<Vk.Instance>());
Ich habe auch versucht zu meiner instance_create_info zu einem anderen IntPtr mit Marshal.StructureToPtr (...) "konvertieren"; und ich habe versucht instance_create_info und instance durch das Schlüsselwort ref übergeben. Offensichtlich hat nichts funktioniert.
Irgendeine Idee?
EDIT:
Die native Funktion wird wie folgt verwendet:
//Definition
typedef struct VkApplicationInfo {
VkStructureType sType;
const void* pNext;
const char* pApplicationName;
uint32_t applicationVersion;
const char* pEngineName;
uint32_t engineVersion;
uint32_t apiVersion;
} VkApplicationInfo;`
typedef struct VkInstanceCreateInfo {
VkStructureType sType;
const void* pNext;
VkInstanceCreateFlags flags;
const VkApplicationInfo* pApplicationInfo;
uint32_t enabledLayerCount;
const char* const* ppEnabledLayerNames;
uint32_t enabledExtensionCount;
const char* const* ppEnabledExtensionNames;
} VkInstanceCreateInfo;
#define VK_DEFINE_HANDLE(object) typedef struct object##_T* object;
VK_DEFINE_HANDLE(VkInstance)
//Code
VkApplicationInfo application_info{};
application_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
application_info.apiVersion = VK_API_VERSION;
application_info.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
application_info.pApplicationName = "";
application_info.engineVersion = VK_MAKE_VERSION(1, 0, 0);
application_info.pEngineName = "";
VkInstanceCreateInfo instance_create_info{};
instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instance_create_info.pApplicationInfo = &application_info;
instance_create_info.enabledLayerCount = 0
instance_create_info.ppEnabledLayerNames = nullptr
instance_create_info.enabledExtensionCount = 0
instance_create_info.ppEnabledExtensionNames = nullptr
VkInstance _instance = nullptr;
assert(!vkCreateInstance(&instance_create_info, nullptr, &_instance));
Es gibt nicht genug Informationen hier zu beantworten. Wir würden beide Seiten der Schnittstelle in vollem Umfang und eine Spezifikation der Semantik benötigen. Oder ein Beispiel C-Code aufrufen. –
@DavidHeffernan Ich habe einen Beispielcode hinzugefügt. Sag mir, wenn du etwas anderes brauchst. – Clematrics
Ich weiß nicht, wie das C# FFI funktioniert, aber "out IntPtr pInstance_Instance" sieht falsch aus. Das Argument out von 'vkCreateInstance' nimmt einen Doppelzeiger auf eine undurchsichtige Struktur; eine Ganzzahl ist möglicherweise nicht groß genug für den Zeiger. –