www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - struggling to link against a C global in D (win/vs2017)

reply DanielG <simpletangent gmail.com> writes:
So I have a DLL+LIB exporting this:

extern "C" {
	extern DLLPROJECT_API int myIntValue;
	DLLPROJECT_API int myIntFunc(int a, int b);
}

In my D app I'm declaring it this way:

extern (C) {
	extern __gshared int myIntValue;
	int myIntFunc (int a, int b);
}

The function seems to link OK, but the C global will not.

Combinations I've tried:

- dmd 32-bit, linked against a coffimplib'ed lib file. This links 
both successfully BUT myIntValue is trashed. myIntFunc does work 
properly however.

- dmd m32mscoff, linking against native VS2017 lib. Complains 
about variable but not the function.

- dmd m64, linking against native VS2017 lib. Complains about the 
variable but not the function.

- ldc2 64-bit, linking against native VS2017 lib. Complains about 
the variable but not the function.

I've examined the .DLL directly and the exported name 
"myIntValue" looks exactly like what dmd/ldc2 are complaining 
they cannot find.

What's the magic recipe here to get this variable linked (and not 
gibberish)?
Oct 28 2018
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Monday, 29 October 2018 at 00:01:21 UTC, DanielG wrote:
 	extern DLLPROJECT_API int myIntValue;
 	extern __gshared int myIntValue;
Both are listed as extern, where is the actual variable stored? If it is in the dll, it shouldn't be extern there.
Oct 28 2018
parent reply DanielG <simpletangent gmail.com> writes:
On Monday, 29 October 2018 at 00:04:54 UTC, Adam D. Ruppe wrote:
 Both are listed as extern, where is the actual variable stored? 
 If it is in the dll, it shouldn't be extern there.
It's defined in the .cpp file. This is how the built-in DLL template generates it - "extern" in the .h file, actual definition in the .cpp file. If you don't have "extern" there, anybody who #includes that .h file would inadvertently have the variable defined, which would result in duplicates (and won't compile).
Oct 28 2018
parent Adam D. Ruppe <destructionator gmail.com> writes:
On Monday, 29 October 2018 at 00:12:43 UTC, DanielG wrote:
 It's defined in the .cpp file.
Ah, of course, good. The other thing that might be an issue is the leading _ the compiler frequently adds. You might be able to hack it with pragma(mangle, "myIntValue") on the declaration too. idk for sure tho.
Oct 28 2018
prev sibling next sibling parent reply Stanislav Blinov <stanislav.blinov gmail.com> writes:
On Monday, 29 October 2018 at 00:01:21 UTC, DanielG wrote:

 In my D app I'm declaring it this way:

 extern (C) {
 	extern __gshared int myIntValue;
 	int myIntFunc (int a, int b);
 }

 The function seems to link OK, but the C global will not.
Should it be extern(Windows), perchance?.. (I haven't D on Windows for ages).
Oct 28 2018
next sibling parent DanielG <simpletangent gmail.com> writes:
On Monday, 29 October 2018 at 00:16:38 UTC, Stanislav Blinov 
wrote:
 Should it be extern(Windows), perchance?.. (I haven't D on 
 Windows for ages).
The stdcall calling convention? I think that would only matter for the function, and indeed, trying that breaks the function being able to link** (and the variable remains broken) ** in 32-bit mscoff mode - no effect on 64-bit (where I think stdcall isn't applicable)
Oct 28 2018
prev sibling parent 12345swordy <alexanderheistermann gmail.com> writes:
On Monday, 29 October 2018 at 00:16:38 UTC, Stanislav Blinov 
wrote:
 On Monday, 29 October 2018 at 00:01:21 UTC, DanielG wrote:

 In my D app I'm declaring it this way:

 extern (C) {
 	extern __gshared int myIntValue;
 	int myIntFunc (int a, int b);
 }

 The function seems to link OK, but the C global will not.
Should it be extern(Windows), perchance?.. (I haven't D on Windows for ages).
Nope, you use export.
Oct 29 2018
prev sibling next sibling parent reply kinke <noone nowhere.com> writes:
On Monday, 29 October 2018 at 00:01:21 UTC, DanielG wrote:
 [...]
I'd examine the dumpbin output of your (native) import library, e.g., `dumpbin /symbols blub.lib`. You can also list exports etc. The names it spits out are undecorated, i.e., C symbols for Win32 libs will feature the implicit _ prefix. A C global in D on Win32 will always get the _ prefix, incl. names overridden via pragma(mangle, 'name') (=> _name). You can cheat by declaring it as `extern(C++)`, where there's no _ prefix. On Win64, there shouldn't be any name decoration for C symbols though.
Oct 28 2018
parent kinke <noone nowhere.com> writes:
On Monday, 29 October 2018 at 00:52:32 UTC, kinke wrote:
 The names it spits out are undecorated
Correction: they *are* the decorated ones, i.e., the real final names.
Oct 28 2018
prev sibling parent reply kinke <noone nowhere.com> writes:
On Monday, 29 October 2018 at 00:01:21 UTC, DanielG wrote:
 DLLPROJECT_API
I guess that's a __declspec(dllexport); in that case try export extern(C) extern __gshared int myIntValue; => that's dllimport for extern variables, and dllexport for non-extern ones.
Oct 28 2018
parent DanielG <simpletangent gmail.com> writes:
On Monday, 29 October 2018 at 01:03:32 UTC, kinke wrote:
 export extern(C) extern __gshared int myIntValue;
Bingo!! That did the trick. Thank you so much.
Oct 28 2018