Re: struggling to link against a C global in D (win/vs2017)

2018-10-28 Thread DanielG via Digitalmars-d-learn

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.



Re: struggling to link against a C global in D (win/vs2017)

2018-10-28 Thread kinke via Digitalmars-d-learn

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.


Re: struggling to link against a C global in D (win/vs2017)

2018-10-28 Thread kinke via Digitalmars-d-learn

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.


Re: struggling to link against a C global in D (win/vs2017)

2018-10-28 Thread kinke via Digitalmars-d-learn

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.


Re: struggling to link against a C global in D (win/vs2017)

2018-10-28 Thread Adam D. Ruppe via Digitalmars-d-learn

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.


Re: struggling to link against a C global in D (win/vs2017)

2018-10-28 Thread DanielG via Digitalmars-d-learn
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)




Re: struggling to link against a C global in D (win/vs2017)

2018-10-28 Thread Stanislav Blinov via Digitalmars-d-learn

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).




Re: struggling to link against a C global in D (win/vs2017)

2018-10-28 Thread DanielG via Digitalmars-d-learn

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).




struggling to link against a C global in D (win/vs2017)

2018-10-28 Thread DanielG via Digitalmars-d-learn

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)?


Re: struggling to link against a C global in D (win/vs2017)

2018-10-28 Thread Adam D. Ruppe via Digitalmars-d-learn

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.


Re: how to make '==' safe for classes?

2018-10-28 Thread ikod via Digitalmars-d-learn

Thanks for excellent explanation!

On Sunday, 28 October 2018 at 19:00:52 UTC, Jonathan M Davis 
wrote:


Because Object predats @safe (and most attributes), it really 
isn't compatible with them. In fact, it predates const (since 
it's basically the same as it was in D1) and it's only possible 
to compare const class objects because of a hack in the free 
function opEquals (which == lowers to) which casts away const 
(meaning that if you're not careful, you can actually violate 
the type system with == by mutating an object in a class'

...
So, unfortunately, for now, you're going to have to use 
@trusted with == on classes, as stupid as that is, though as a 
workaround, you could always create an @trusted wrapper 
function that just called ==. It would still be annoying, but 
it would be cleanly restricted the @trusted bits.


- Jonathan M Davis





Re: how to make '==' safe for classes?

2018-10-28 Thread Jonathan M Davis via Digitalmars-d-learn
On Sunday, October 28, 2018 12:56:10 PM MDT ikod via Digitalmars-d-learn 
wrote:
> On Sunday, 28 October 2018 at 18:00:06 UTC, Stanislav Blinov
>
> wrote:
> > On Sunday, 28 October 2018 at 12:38:12 UTC, ikod wrote:
> >> and object.opEquals(a,b) do not inherits safety from class C
> >> properties, and also I can't override it.
> >
> > Yep. Since Object is the base class and it defines opEquals as:
> object.opEquals(a,b) even is not a Object member function, it's
> free function.
>
> It looks a bit unnatural for me, but thanks for confirmation!

It may seem weird at first, but it actually solves several problems that you
get when simple calling a.obEquals(b) - the most obvious of which is that
a.opEquals(b) has to worry about null, which opEquals(a, b) solves for you,
but if you look at the implementation I posted elsewhere in the thread, it
solves some other problems as well. It's one of those places where D was
able to learn from problems that languages that came before it had.
Unfortunately, the attribute problem is _not_ one of those areas.

- Jonathan M Davis





Re: how to make '==' safe for classes?

2018-10-28 Thread Jonathan M Davis via Digitalmars-d-learn
On Sunday, October 28, 2018 6:38:12 AM MDT ikod via Digitalmars-d-learn 
wrote:
> Hello
>
> How to make this code to compile? My goal is safe(not @trusted)
> longFunction().
>
>
> ---
> class C
> {
>  override bool opEquals(Object o) const @safe
>  {
>  return true;
>  }
> }
> bool longFunction(C a, C b) @safe
> {
>  return a==b;
> }
> void main()
> {
> }
> ---
>
>
> As far as I understand the problem is that AST for this code
> looks like
>
> ---
> import object;
> class C : Object
> {
>   override const @safe bool opEquals(Object o)
>   {
>   return true;
>   }
> }
> bool longFunction(C a, C b)
> {
>   return opEquals(a, b);
> }
> void main()
> {
>   return 0;
> }
> RTInfo!(C)
> {
>   enum typeof(null) RTInfo = null;
>
> }
> ---
>
> and object.opEquals(a,b) do not inherits safety from class C
> properties, and also I can't override it.
>
> Is there clean way to use '==' here, or I have to convert this to
> a.opEquals(b) for classes, leaving '==' for structs?
>
> Thanks!

Because Object predats @safe (and most attributes), it really isn't
compatible with them. In fact, it predates const (since it's basically the
same as it was in D1) and it's only possible to compare const class objects
because of a hack in the free function opEquals (which == lowers to) which
casts away const (meaning that if you're not careful, you can actually
violate the type system with == by mutating an object in a class' opEquals).
And because attributes are inherited, even if we were willing to break
existing code by changing the attributes on Object, there really isn't a
good way to fix the problem, because whatever set of attributes we picked
(for @safe, nothrow, const, etc.) would work for some programs but not
others. That's why at one point, it was decided that we would remove all of
the various member functions from Object. Given the templates in D, they
really aren't necessary like they are in languages like Java. As long as
stuff like the built in AA implementation is templated (which it
unfortunately is not right now), all of the appropriate information can be
inferred, and it's not necessary to have a root class object with member
functions like opEquals in order to use it in generic code.

https://issues.dlang.org/show_bug.cgi?id=9769
https://issues.dlang.org/show_bug.cgi?id=9770
https://issues.dlang.org/show_bug.cgi?id=9771
https://issues.dlang.org/show_bug.cgi?id=9772

However, while that decision was made some time ago, actually implementing
it isn't easy, and the necessary steps have never happened - to the point
that it doesn't seem very likely at this point. What seems far more likely
is a DIP that Andrei has proposed:

https://github.com/andralex/DIPs/blob/ProtoObject/DIPs/DIP.md

It will introduce ProtoObject as a new root object below Object which does
not have any member functions or an embedded monitor object (which is only
necessary if you actually have synchronized functions). Object would stay
the default base class (since code would break otherwise), and any code
using Object would unfortunately continue to have the same problems, but
classes that then explicitly derive from ProtoObject would be able to define
opEquals, opCmp, toString, etc. with the signatures that were appropriate to
the applications or libraries that they're in. Any classes derived from such
classes would then be stuck with those attributes just like we're stuck with
the attributes on Object right now, but those choices would then be per
object hierarchy rather than forced on everyone using the language. So, it
looks like that's probably going to be the ultimate fix for this problem,
but we don't really have an ETA at the moment.

So, unfortunately, for now, you're going to have to use @trusted with == on
classes, as stupid as that is, though as a workaround, you could always
create an @trusted wrapper function that just called ==. It would still be
annoying, but it would be cleanly restricted the @trusted bits.

- Jonathan M Davis





Re: how to make '==' safe for classes?

2018-10-28 Thread ikod via Digitalmars-d-learn
On Sunday, 28 October 2018 at 18:00:06 UTC, Stanislav Blinov 
wrote:

On Sunday, 28 October 2018 at 12:38:12 UTC, ikod wrote:

and object.opEquals(a,b) do not inherits safety from class C 
properties, and also I can't override it.


Yep. Since Object is the base class and it defines opEquals as:


object.opEquals(a,b) even is not a Object member function, it's 
free function.


It looks a bit unnatural for me, but thanks for confirmation!



```
bool opEquals(Object);
```

the compiler rewrites `a == b` as 
`(cast(Object)a).opEquals(cast(Object)ob)`, i.e. it inserts a 
@system call into your code.


Is there clean way to use '==' here, or I have to convert this 
to a.opEquals(b) for classes, leaving '==' for structs?


Pretty much, yes. "Implicit" value comparison in general is 
somewhat alien for classes, since they're reference types.





Re: how to make '==' safe for classes?

2018-10-28 Thread Jonathan M Davis via Digitalmars-d-learn
On Sunday, October 28, 2018 12:17:41 PM MDT Neia Neutuladh via Digitalmars-
d-learn wrote:
> On Sun, 28 Oct 2018 18:00:06 +, Stanislav Blinov wrote:
> > On Sunday, 28 October 2018 at 12:38:12 UTC, ikod wrote:
> >> and object.opEquals(a,b) do not inherits safety from class C
> >> properties, and also I can't override it.
> >
> > Yep. Since Object is the base class and it defines opEquals as:
> > ```
> > bool opEquals(Object);
> > ```
> >
> > the compiler rewrites `a == b` as
> > `(cast(Object)a).opEquals(cast(Object)ob)`, i.e. it inserts a @system
> > call into your code.
>
> More pedantically, it rewrites it as:
>
>   (a is b) ||
>   (a !is null && (cast(Object)a).opEquals(cast(Object)b))
>
> An object might not be equal to itself via opEquals, but it will always
> compare equal to itself with ==.

Technically, it calls the free function opEquals in object.d, which does
more than that (including introduce a hack to work around the type system to
allow comparing const objects). Specifically, the current implementation is

bool opEquals(Object lhs, Object rhs)
{
// If aliased to the same object or both null => equal
if (lhs is rhs) return true;

// If either is null => non-equal
if (lhs is null || rhs is null) return false;

// If same exact type => one call to method opEquals
if (typeid(lhs) is typeid(rhs) ||
!__ctfe && typeid(lhs).opEquals(typeid(rhs)))
/* CTFE doesn't like typeid much. 'is' works, but opEquals 
doesn't
(issue 7147). But CTFE also guarantees that equal TypeInfos are
always identical. So, no opEquals needed during CTFE. */
{
return lhs.opEquals(rhs);
}

// General case => symmetric calls to method opEquals
return lhs.opEquals(rhs) && rhs.opEquals(lhs);
}

/
* Returns true if lhs and rhs are equal.
*/
bool opEquals(const Object lhs, const Object rhs)
{
// A hack for the moment.
return opEquals(cast()lhs, cast()rhs);
}

- Jonathan M Davis





Re: how to make '==' safe for classes?

2018-10-28 Thread Neia Neutuladh via Digitalmars-d-learn
On Sun, 28 Oct 2018 18:00:06 +, Stanislav Blinov wrote:

> On Sunday, 28 October 2018 at 12:38:12 UTC, ikod wrote:
> 
>> and object.opEquals(a,b) do not inherits safety from class C
>> properties, and also I can't override it.
> 
> Yep. Since Object is the base class and it defines opEquals as:
> ```
> bool opEquals(Object);
> ```
> 
> the compiler rewrites `a == b` as
> `(cast(Object)a).opEquals(cast(Object)ob)`, i.e. it inserts a @system
> call into your code.

More pedantically, it rewrites it as:

  (a is b) ||
  (a !is null && (cast(Object)a).opEquals(cast(Object)b))

An object might not be equal to itself via opEquals, but it will always 
compare equal to itself with ==.


Re: how to make '==' safe for classes?

2018-10-28 Thread Stanislav Blinov via Digitalmars-d-learn

On Sunday, 28 October 2018 at 12:38:12 UTC, ikod wrote:

and object.opEquals(a,b) do not inherits safety from class C 
properties, and also I can't override it.


Yep. Since Object is the base class and it defines opEquals as:
```
bool opEquals(Object);
```

the compiler rewrites `a == b` as 
`(cast(Object)a).opEquals(cast(Object)ob)`, i.e. it inserts a 
@system call into your code.


Is there clean way to use '==' here, or I have to convert this 
to a.opEquals(b) for classes, leaving '==' for structs?


Pretty much, yes. "Implicit" value comparison in general is 
somewhat alien for classes, since they're reference types.


how to make '==' safe for classes?

2018-10-28 Thread ikod via Digitalmars-d-learn

Hello

How to make this code to compile? My goal is safe(not @trusted) 
longFunction().



---
class C
{
override bool opEquals(Object o) const @safe
{
return true;
}
}
bool longFunction(C a, C b) @safe
{
return a==b;
}
void main()
{
}
---


As far as I understand the problem is that AST for this code 
looks like


---
import object;
class C : Object
{
override const @safe bool opEquals(Object o)
{
return true;
}
}
bool longFunction(C a, C b)
{
return opEquals(a, b);
}
void main()
{
return 0;
}
RTInfo!(C)
{
enum typeof(null) RTInfo = null;

}
---

and object.opEquals(a,b) do not inherits safety from class C 
properties, and also I can't override it.


Is there clean way to use '==' here, or I have to convert this to 
a.opEquals(b) for classes, leaving '==' for structs?


Thanks!


Re: link errors when using extern (C) structs

2018-10-28 Thread rikki cattermole via Digitalmars-d-learn

On 28/10/2018 11:11 PM, DanielG wrote:


Wait, wut? Do modules that get pulled in from dub's "importPaths" not 
get compiled in the same way?


No. They just get -I'd.


Re: link errors when using extern (C) structs

2018-10-28 Thread DanielG via Digitalmars-d-learn

On Sunday, 28 October 2018 at 08:38:56 UTC, Nicholas Wilson wrote:
Oh yeah, I didn't think to mention that you need to compile 
them for them to fix your missing symbols problem.


Wait, wut? Do modules that get pulled in from dub's "importPaths" 
not get compiled in the same way?


The dstep-generated files were working for the most part -- 
standalone C functions had no problem -- it was only those 
structs that I was having problems with. But now that they're in 
the default /source folder, I don't get the linker errors 
anymore. 





Re: link errors when using extern (C) structs

2018-10-28 Thread Nicholas Wilson via Digitalmars-d-learn

On Sunday, 28 October 2018 at 06:59:31 UTC, DanielG wrote:
For the benefit of anybody who encounters a problem like this 
in the future ... originally I had my C library "header" files 
(renamed from .di to .d after the feedback from Nicholas) in a 
special 'headers/' subdir, used as an import path in dub.json. 
I simply moved those files to the source folder and everything 
started magically working.


And thanks again, Nicholas!


Oh yeah, I didn't think to mention that you need to compile them 
for them to fix your missing symbols problem.


No problems.


Re: link errors when using extern (C) structs

2018-10-28 Thread DanielG via Digitalmars-d-learn
For the benefit of anybody who encounters a problem like this in 
the future ... originally I had my C library "header" files 
(renamed from .di to .d after the feedback from Nicholas) in a 
special 'headers/' subdir, used as an import path in dub.json. I 
simply moved those files to the source folder and everything 
started magically working.


And thanks again, Nicholas!