Created attachment 1581
test case
D:
------------------
module lib;
extern(C++) class C
{
}
extern(C++) interface I
{
void f();
}
extern(C++) abstract class BaseImpl(C, I) : I
{
C instance;
}
// Bonus points: this is extern(C) because the C++ mangler doesn't work on this type.
extern(C) void test(BaseImpl!(C, I) impl)
{
impl.f();
}
C++:
------------------
#include <stdio.h>
class C
{
};
class I
{
virtual void f() = 0;
};
template <typename C, typename I>
class BaseImpl : public I
{
C *pInstance = (C*)(size_t)0xBAADF00D;
};
class Impl : public BaseImpl<C, I>
{
void f() override final
{
printf("!!");
}
};
extern "C" {
extern void test(BaseImpl<C, I> *pImpl);
}
void main()
{
Impl *i = new Impl;
test(i);
}
Comment #1 by bugzilla — 2016-01-30T07:54:53Z
Thanks, Manu. The first thing I notice is main() is in C++. This will not work because it will bypass the D runtime initialization. That isn't what this bug is about, though. I'll see what I can do with this.
Comment #2 by bugzilla — 2016-01-30T08:15:06Z
Stripping away the unnecessary template and complex names:
---------- D -----------------
extern(C++)
{
class C { }
interface I
{
void f();
}
abstract class Base : I
{
int instance;
}
void test(Base b)
{
b.f();
}
void mainx();
}
int main()
{
mainx();
return 0;
}
------------- C++ ------------
#include <stdio.h>
class C { };
class I
{
virtual void f() = 0;
};
class Base : public I
{
public:
int pInstance;
Base() { pInstance = 0xBAADF00D; }
};
class Derived : public Base
{
public:
void f() { printf("!!"); }
};
void test(Base *b);
void mainx()
{
Derived *d = new Derived;
test(d);
}
Comment #3 by bugzilla — 2016-02-01T04:09:52Z
As a workaround, if you create a base class for 'Base' that contains a virtual function, in both the D and C++ code, it will work.
Comment #4 by bugzilla — 2016-02-05T10:52:21Z
https://github.com/D-Programming-Language/dmd/pull/5403
There's no easy way to hack this in. The trouble is you have a C++ base class with no virtual functions, so it has no vtbl[]. I.e. is it not a class at all, it is a struct. This is not supported.
The way to fix the code is to replace interface I with abstract class I, move the fields from C into I, and ditch class C entirely.
Comment #5 by github-bugzilla — 2016-02-06T17:10:06Z