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









RSY <rsy_881 gmail.com> 