Hi,
On 20/01/2021 20:30, Frederik Seiffert wrote:
There’s one more issue though: both [Test class] and [Test new] (with "Test"
being defined in the DLL) only return null pointers in my testing. However subclassing
the Test root class locally works fine and allows instantiating the subclass, as does a
locally defined root class (same implementation as Test).
The following code (with "Sub" being a subclass of "Test"):
printf("%p %p\n", [Test class], [Test new]);
printf("%p %p\n", [Sub class], [Sub new]);
Prints:
0000000000000000 0000000000000000
00007FF73EDB0080 00000291D99247A8
Any idea? All other things I tried so far seemed to be working fine, though I’m
sure this won’t be the last of my questions...
I think I misrememberd some details of the Windows ABI. I wrote a
little test compilation unit to look at it:
```obj-c
__attribute__((dllimport))
@interface Test
+ (id)new;
@end
@interface Sub : Test @end
@implementation Sub
+ (id)new
{
return (void*)1;
}
@end
int main(void)
{
[Test new];
[Sub new];
}
```
And compiled it with:
clang11 -S -fobjc-runtime=gnustep-2.0 -target x86_64-pc-windows-msvc
-O1 -o - msg.m -emit-llvm
This generates a global like this:
```llvm
@"$_OBJC_CLASS_Test" = external dllimport global i8*
```
This is a dllimport'd global, so one that can be referenced in the
instruction stream and will have relocations applied. It can't be
referenced in a global and so there's an `.objc_early_init` function
generated that initialises the isa pointer of the `Sub` class.
The message sends both directly load from the `_REF_` class pointer,
which is declared like this:
```llvm
@"$_OBJC_REF_CLASS_Test" = external dllimport local_unnamed_addr global i8*
```
So this has a canonical home in the DLL that owns the class and every
other message send must indirect via that. Without the dllimport
qualifier, clang generates:
```llvm
@"$_OBJC_CLASS_Test" = external global i8*
@"$_OBJC_REF_CLASS_Test" = external local_unnamed_addr global i8*
```
These are both local to the DLL or EXE that contains them and won't be
correctly initialised.
It looks as if you are missing the dllimport attribute on the classes
that you're referencing from another DLL.
In WinObjC, all of the classes are decorated with a macro that does the
normal Windows dance of expanding to dllimport normally and dllexport
when you are building the DLL that they come from. These are missing
from GNUstep, I'm not sure if you added them in your branch.
David