Thread overview
Making a forward declaration of a C symbol defined in another CU
Dec 20, 2018
Alexander Nicholi
Dec 20, 2018
Dennis
Dec 20, 2018
Alexander Nicholi
Dec 20, 2018
Dennis
Dec 20, 2018
Joakim
December 20, 2018
I'm developing for Windows, 64-bit at the moment with MSVC and DMD. I have this C code file, config.c:

    #define STRINGIZE( x ) STRINGIZE_( x )
    #define STRINGIZE_( x ) #x

    const xu16 ocoCoreVerMajor   = _MILES_VER_MAJOR;
    const xu16 ocoCoreVerMinor   = _MILES_VER_MINOR;
    const xu16 ocoCoreVerPatch   = _MILES_VER_PATCH;
    const char* ocoCoreVerBuild  = STRINGIZE( _MILES_VER_BUILD );
    const char* ocoCoreTimestamp = STRINGIZE( _MILES_BUILD_TSTAMP );

And for D code, I have this interface, config.d:

    module oco.core.config;

    extern (C) const ushort ocoCoreVerMajor;
    extern (C) const ushort ocoCoreVerMinor;
    extern (C) const ushort ocoCoreVerPatch;
    extern (C) const char* ocoCoreVerBuild;
    extern (C) const char* ocoCoreTimestamp;

The linker gives me this error:

    [ÔÇô/debug] Linking         oco...
    [ÔÇô/debug stop] config.d.obj : error LNK2005: ocoCoreVerMajor already defined in
    config.c.obj
    ...
    [ÔÇô/debug stop] C:\Users\Alex\AppData\Local\Temp\miles-build\oco.exe : fatal error LNK1169: one or more multiply defined symbols found
    [ÔÇô/debug stop]

I figure the D code is defining symbols redundantly, and they're not weakly defined, so this happens. Obviously I can't exactly just hand the definitions into D, as you can see by the C code this is actually the best way to pass these values around across language boundaries (there are a few). How do I tell D to treat this right?
December 20, 2018
On Thursday, 20 December 2018 at 08:17:58 UTC, Alexander Nicholi wrote:
>
>     extern (C) const ushort ocoCoreVerMajor;
>     extern (C) const ushort ocoCoreVerMinor;
>     extern (C) const ushort ocoCoreVerPatch;
>     extern (C) const char* ocoCoreVerBuild;
>     extern (C) const char* ocoCoreTimestamp;

Mark these as external, so extern(C) extern const ...

December 20, 2018
On Thursday, 20 December 2018 at 08:17:58 UTC, Alexander Nicholi wrote:
> I'm developing for Windows, 64-bit at the moment with MSVC and DMD. I have this C code file, config.c:
>
> [...]

This belongs in the Learn forum:

https://forum.dlang.org/group/learn

See the docs on interfacing to C globals, you need the additional `extern` storage class:

https://dlang.org/spec/interfaceToC.html#c-globals
https://dlang.org/spec/declaration.html#extern
December 20, 2018
On Thursday, 20 December 2018 at 08:27:55 UTC, Dennis wrote:
> On Thursday, 20 December 2018 at 08:17:58 UTC, Alexander Nicholi wrote:
>>
>>     extern (C) const ushort ocoCoreVerMajor;
>>     extern (C) const ushort ocoCoreVerMinor;
>>     extern (C) const ushort ocoCoreVerPatch;
>>     extern (C) const char* ocoCoreVerBuild;
>>     extern (C) const char* ocoCoreTimestamp;
>
> Mark these as external, so extern(C) extern const ...

Oh, that works fine, thanks. I thought I already did that with the extern (C), but I guess that's a different kind of extern isn't it
December 20, 2018
On Thursday, 20 December 2018 at 08:31:53 UTC, Alexander Nicholi wrote:
> Oh, that works fine, thanks. I thought I already did that with the extern (C), but I guess that's a different kind of extern isn't it

Indeed, extern(C) only changes the mangled name and calling convention, it doesn't also mark variables as extern.