www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - DMD: can't get extern __gshared to work right (vs. LDC)

reply DanielG <simpletangent gmail.com> writes:
macOS 12, DMD 2.084.0 / LDC 1.14.0-beta1

I have a C API that exports some global variables, declared like 
so:

.h file:
=====
extern "C" {
#define PUBLIC_API __attribute__((visibility("default")))
struct __opaqueHandle; typedef __opaqueHandle* opaqueHandle_t;
PUBLIC_API extern const opaqueHandle_t kSomeGlobalValue;
}

.cpp file:
======
const opaqueHandle_t kSomeGlobalValue = (opaqueHandle_t) 
kSomeInternalPointer;

.d file:
====
extern (C):
export extern __gshared opaqueHandle_t kSomeGlobalValue;


I have no issues linking against the resulting .dylib with a 
C/C++ program, nor issues with DMD on Windows with the same code. 
However with DMD on macOS, the value is coming through 
incorrectly. It looks like a valid pointer value (vs. pure 
garbage), but it's still incorrect. LDC2 works fine, no issues.

Is there some extra flag I need to pass to DMD on Mac to get it 
to see this global properly? It links fine, no errors, but the 
value is still wrong. I should also mention that this dylib 
exports functions, too, and they are working fine even with DMD. 
It's just the globals I'm having problems with.
Feb 06 2019
parent reply DanielG <simpletangent gmail.com> writes:
Follow-up:

The problem on DMD macOS is the "export" keyword. It ended up in 
my code during a similar-ish problem last year, when I was having 
trouble linking against DLL global variables on Windows.

If I remove the "export" keyword in the D interface, it will work 
on macOS but break on Windows. (To reiterate: WITHOUT "export" on 
Windows, it refuses to link. WITH "export" on Mac, it seems to 
link but with incorrect results)

Is this correct behavior?
Feb 07 2019
parent reply Kagamin <spam here.lot> writes:
On Friday, 8 February 2019 at 05:28:30 UTC, DanielG wrote:
 Is this correct behavior?
It's correct for Windows: address of imported data is not known at link time and must use dynamic linkage. AFAIK, export attribute doesn't do much on posix platforms.
Feb 07 2019
parent reply DanielG <simpletangent gmail.com> writes:
On Friday, 8 February 2019 at 07:52:26 UTC, Kagamin wrote:
 AFAIK, export attribute doesn't do much on posix platforms.
I created a minimal example and it definitely segfaults at runtime in the presence of "export" (on Mac, haven't tested linux). So it's required for Windows and silently evil for Mac... Any reason I shouldn't file a DMD bug for this?
Feb 08 2019
parent reply rikki cattermole <rikki cattermole.co.nz> writes:
On 08/02/2019 9:14 PM, DanielG wrote:
 On Friday, 8 February 2019 at 07:52:26 UTC, Kagamin wrote:
 AFAIK, export attribute doesn't do much on posix platforms.
I created a minimal example and it definitely segfaults at runtime in the presence of "export" (on Mac, haven't tested linux). So it's required for Windows and silently evil for Mac... Any reason I shouldn't file a DMD bug for this?
File, inconsistent behavior is inconsistent. Not good.
Feb 08 2019
parent reply DanielG <simpletangent gmail.com> writes:
On Friday, 8 February 2019 at 09:19:12 UTC, rikki cattermole 
wrote:
 File, inconsistent behavior is inconsistent. Not good.
done: https://issues.dlang.org/show_bug.cgi?id=19660
Feb 08 2019
parent reply DanielG <simpletangent gmail.com> writes:
In the meantime, while I'm waiting for this bug to be noticed by 
anybody with the skills to address it, what would be the most 
elegant way of working around it?

Obviously I could do a:

version(Windows) {
   export extern __gshared ...
} else {
   extern __gshared ...
}

But what's the minimal way of toggling the presence of "export" 
in a declaration? Using mixins feels kind of gross for this, but 
if that's the only option ...

Almost makes me long for the C preprocessor :P
Feb 18 2019
parent rikki cattermole <rikki cattermole.co.nz> writes:
On 19/02/2019 6:26 AM, DanielG wrote:
 In the meantime, while I'm waiting for this bug to be noticed by anybody 
 with the skills to address it, what would be the most elegant way of 
 working around it?
 
 Obviously I could do a:
 
 version(Windows) {
    export extern __gshared ...
 } else {
    extern __gshared ...
 }
 
 But what's the minimal way of toggling the presence of "export" in a 
 declaration? Using mixins feels kind of gross for this, but if that's 
 the only option ...
 
 Almost makes me long for the C preprocessor :P
Because you need two different versions to choose between them, either set a per module version or use static if with enum's. But yeah, I would do that. Of course a mixin template with a code string (q{ ... }) would be cleaner. After all, ``export { mixin(str); }`` would work well.
Feb 18 2019