digitalmars.D.learn - C++ interop, abstract struct problem
- RSY (102/102) Dec 28 2020 Hello
- RSY (4/4) Dec 28 2020 IAllocator struct:
- Paul Backus (4/9) Dec 28 2020 You could try using one of the techniques on this page to make
Hello I try to use a C++ lib So far so good, i managed to use that lib and get started The problem however is this: C++ API: ``` void preinit(IAllocator& allocator, bool load_renderdoc); ``` ``IAllocator`` is an abstract struct, (a struct with virtual functions) But the problem is D doesn't allow that, so apparently i need to use an abstract class and wrap it using: ``extern (C++, struct)`` The problem is, when passing the object to the function i get: ``dumix.obj : error LNK2019: unresolved external symbol "void __cdecl Lumix::gpu::preinit(struct Lumix::IAllocator *,bool)" (?preinit gpu Lumix YAXPEAUIAllocator 2 _N Z) referenced in function _Dmain `` Wich is wrong, it is supposed to pass as a reference, i don't know why it is picky Do you guys have an idea what i do wrong, or what i should do? Thanks! Here is the full code: ``` import std.stdio; import core.thread; import core.stdc.stdio; import core.memory; extern (C++, Lumix) nogc nothrow { extern (C++, os) nogc nothrow { struct InitWindowArgs { enum Flags { NO_DECORATION = 1 << 0, NO_TASKBAR_ICON = 1 << 1 } const(char)* name = "hello lumix"; bool handle_file_drops = false; bool fullscreen = false; uint flags = 0; void* parent = null; } void* createWindow(const ref InitWindowArgs); } align(8) struct Mutex { ubyte[8] data; } extern (C++, struct) abstract class IAllocator { void* allocate(size_t n); void deallocate(void* p); void* reallocate(void* ptr, size_t size); void* allocate_aligned(size_t size, size_t alignn); void deallocate_aligned(void* ptr); void* reallocate_aligned(void* ptr, size_t size, size_t alignn); } extern (C++, struct) class DefaultAllocator : IAllocator { ubyte* m_small_allocations = null; void*[4] m_free_lists; uint m_page_count = 0; Mutex m_mutex; override void* allocate(size_t n); override void deallocate(void* p); override void* reallocate(void* ptr, size_t size); override void* allocate_aligned(size_t size, size_t alignn); override void deallocate_aligned(void* ptr); override void* reallocate_aligned(void* ptr, size_t size, size_t alignn); } extern (C++, gpu) nogc nothrow { enum InitFlags : uint { NONE = 0, DEBUG_OUTPUT = 1 << 0, VSYNC = 1 << 1 } // 1505C2 ?preinit gpu Lumix YAXAEAUIAllocator 2 _N Z void preinit(IAllocator allocator, bool load_renderdoc); bool init(void* window_handle, InitFlags flags); void* allocProgramHandle(); } } void main() { auto arg = InitWindowArgs(); auto win = Lumix.os.createWindow(arg); IAllocator allocator = new DefaultAllocator(); Lumix.gpu.preinit(allocator, false); Lumix.gpu.init(win, InitFlags.NONE); while (true) { Thread.sleep(usecs(1)); } } ```
Dec 28 2020
IAllocator struct: https://github.com/nem0/LumixEngine/blob/master/src/engine/allocator.h#L18 function: https://github.com/nem0/LumixEngine/blob/master/src/renderer/gpu/gpu.h#L208
Dec 28 2020
On Monday, 28 December 2020 at 15:42:26 UTC, RSY wrote:``IAllocator`` is an abstract struct, (a struct with virtual functions) But the problem is D doesn't allow that, so apparently i need to use an abstract class and wrap it using: ``extern (C++, struct)``You could try using one of the techniques on this page to make `IAllocator` a struct instead of a class: https://dlang.org/spec/cpp_interface.html#structs
Dec 28 2020
On Monday, 28 December 2020 at 16:42:19 UTC, Paul Backus wrote:On Monday, 28 December 2020 at 15:42:26 UTC, RSY wrote:Oh i wonder how i could have missed this part, thanks!! i will try this``IAllocator`` is an abstract struct, (a struct with virtual functions) But the problem is D doesn't allow that, so apparently i need to use an abstract class and wrap it using: ``extern (C++, struct)``You could try using one of the techniques on this page to make `IAllocator` a struct instead of a class: https://dlang.org/spec/cpp_interface.html#structs
Dec 28 2020
Hmm, something seems to be very wrong, here what i got so far ``` D struct IAllocator { } struct DefaultAllocator { // BASE -------------------------- IAllocator base = IAllocator(); alias base this; //-------------------------------- ubyte* m_small_allocations = null; void*[4] m_free_lists; uint m_page_count = 0; Mutex m_mutex; } void preinit(ref IAllocator allocator, bool load_renderdoc); ``` The problem is the allocator data seems to be corrupted, it crashes on the C++ side when calling preinit IAllocator is empty, but it doesn't get optimized as the wiki say, since the size of DefaultAllocator is 64 bytes on the C++ side, and 56 bytes on D side, i get 64 bytes with the definition above Does anyone have an idea, did i translate the struct wrong? ```C++ struct LUMIX_ENGINE_API IAllocator { virtual ~IAllocator() {} virtual bool isDebug() const { return false; } virtual void* allocate(size_t size) = 0; virtual void deallocate(void* ptr) = 0; virtual void* reallocate(void* ptr, size_t size) = 0; virtual void* allocate_aligned(size_t size, size_t align) = 0; virtual void deallocate_aligned(void* ptr) = 0; virtual void* reallocate_aligned(void* ptr, size_t size, size_t align) = 0; template <typename T> void deleteObject(T* ptr) { if (ptr) { ptr->~T(); deallocate_aligned(ptr); } } }; ``` and for DefaultAllocator ```c++ struct LUMIX_ENGINE_API DefaultAllocator final : IAllocator { struct Page; DefaultAllocator(); ~DefaultAllocator(); void* allocate(size_t n) override; void deallocate(void* p) override; void* reallocate(void* ptr, size_t size) override; void* allocate_aligned(size_t size, size_t align) override; void deallocate_aligned(void* ptr) override; void* reallocate_aligned(void* ptr, size_t size, size_t align) override; u8* m_small_allocations = nullptr; Page* m_free_lists[4]; u32 m_page_count = 0; Mutex m_mutex; }; ``` For Mutex: ```c++ struct alignas(8) LUMIX_ENGINE_API Mutex { friend struct ConditionVariable; Mutex(); Mutex(const Mutex&) = delete; ~Mutex(); void enter(); void exit(); private: #ifdef _WIN32 u8 data[8]; #else pthread_mutex_t mutex; #endif }; ```
Dec 29 2020
Here is a debugger view of the passed IAllocator& https://i.imgur.com/p04Tj4a.png
Dec 29 2020