Thread overview |
---|
December 28, 2020 C++ interop, abstract struct problem | ||||
---|---|---|---|---|
| ||||
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)); } } ``` |
December 28, 2020 Re: C++ interop, abstract struct problem | ||||
---|---|---|---|---|
| ||||
Posted in reply to RSY | 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 |
December 28, 2020 Re: C++ interop, abstract struct problem | ||||
---|---|---|---|---|
| ||||
Posted in reply to RSY | 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 |
December 28, 2020 Re: C++ interop, abstract struct problem | ||||
---|---|---|---|---|
| ||||
Posted in reply to Paul Backus | 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:
>> ``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
Oh i wonder how i could have missed this part, thanks!! i will try this
|
December 29, 2020 Re: C++ interop, abstract struct problem | ||||
---|---|---|---|---|
| ||||
Posted in reply to RSY | 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 }; ``` |
December 29, 2020 Re: C++ interop, abstract struct problem | ||||
---|---|---|---|---|
| ||||
Posted in reply to RSY | Here is a debugger view of the passed IAllocator& https://i.imgur.com/p04Tj4a.png |
Copyright © 1999-2021 by the D Language Foundation