So recently I have been working with Vulkan-Hpp
(The official c++ bindings of Vulkan Api, Github Link).
Looking into the source, I have found that they create wrapper classes around native Vulkan structs (e.g. vk::InstanceCreateInfo
wraps around VkInstanceCreateInfo
). (Note: Wrapping around, not deriving from)
When calling native Vulkan API, the pointers to wrapper classes are reinterpret_cast
ed into the native Vulkan structs. An example using vk::InstanceCreateInfo
:
//definition of vk::InstanceCreateInfo
struct InstanceCreateInfo
{
/* member function omitted */
private:
StructureType sType = StructureType::eInstanceCreateInfo;
public:
const void* pNext = nullptr;
InstanceCreateFlags flags;
const ApplicationInfo* pApplicationInfo;
uint32_t enabledLayerCount;
const char* const* ppEnabledLayerNames;
uint32_t enabledExtensionCount;
const char* const* ppEnabledExtensionNames;
};
//definition of VkInstanceCreateInfo
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;
//And the usage where reinterpret_cast takes place
template<typename Dispatch>
VULKAN_HPP_INLINE ResultValueType<Instance>::type createInstance( const InstanceCreateInfo &createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d )
{
Instance instance;
Result result = static_cast<Result>( d.vkCreateInstance( reinterpret_cast<const VkInstanceCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkInstance*>( &instance ) ) );
return createResultValue( result, instance, VULKAN_HPP_NAMESPACE_STRING"::createInstance" );
}
So my question is: vk::InstanceCreateInfo
and VkInstanceCreateInfo
are two different types. Moreover, VkInstanceCreateInfo
is standard layout but vk::InstanceCreateInfo
is not (since it has mixed access specifiers). Is reinterpret_cast
ing between the pointer of those two types (as done by Vulkan-Hpp
) legal? Does this violate the strict aliasing rule?
Note: you can assume that VkInstanceCreateFlags
and vk::InstanceCreateFlags
are interchangeable in this case (otherwise it would make my question recursive)
reinterpret_cast
are everywhere around the library (I've checked the macros, and verified that it is not a compiler specific feature). And about access specifiers,All non-static data members have the same access control
in order for a class to be standard layout. – Shouteffective types
(which simply meanstype
when the type is declared). So this means even those two types are both standard layout types and have exact same members, type punning is not allowed. Maybe the correct way is to use inheritance? Feel free to correct me if I am wrong. – Shout