www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Making a forward declaration of a C symbol defined in another CU

reply Alexander Nicholi <alex arqadium.com> writes:
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?
Dec 20 2018
next sibling parent reply Dennis <dkorpel gmail.com> writes:
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 ...
Dec 20 2018
parent reply Alexander Nicholi <alex arqadium.com> writes:
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
Dec 20 2018
parent Dennis <dkorpel gmail.com> writes:
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.
Dec 20 2018
prev sibling parent Joakim <dlang joakim.fea.st> writes:
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
Dec 20 2018