Re: C++ constructors, destructors and operator access

2013-05-20 Thread evilrat

On Saturday, 18 May 2013 at 22:23:51 UTC, Igor Stepanov wrote:
At the current time D have powerful mechanism of access to C++ 
classes.
For access to methods of C++ classes (virtual and not) we can 
use extern(C++) interface.


//С++

class CPPTest1
{
int a;
int b;
  public:
virtual int boom();
int fun();
static int gun();
CPPTest1(int);
virtual ~CPPTest1();
int operator[](size_t);
};

class CPPTest2: public CPPTest1
{
int boom();
};

//D
extern(C++)interface CPPTest1
{
int boom();
static int gun();
final int fun();
}

extern(C++)interface CPPTest2: CPPTest1
{
//int boom();
}



As a rule, non-static fields are not public in C++ classes and 
is not part of interface. Thus the most of C++ classes can be 
bound without any glue c++ code.
However D dont support C++ overloaded operators and 
constructors. Yes, we cannot make mapping C++ operators to D 
operators and C++ constructors to D constructors). Nonetheless 
С++ operators and constructors are the simple C++ functions or 
methods with special mangling. Thus I've suggest next mechanism:
Allow special pragma(cppSymbol, string_arg), when string_arg is 
the name of c++ thing.

Example:

extern(C++)interface CPPTest1
{
int boom();
static int gun();
final int fun();
///
pragma(cppSymbol, constructor) final void ctor(int); 
//linked with CPPTest1(int);
pragma(cppSymbol, destructor) void dtor(); //linked with 
virtual ~CPPTest1();
pragma(cppSymbol, []) ref int indexOf(size_t); //linked 
with int operator[](size_t);

}

This pragma must apply to the function (or method), use natural 
C++ mangle, but set operatror or constructor or destructor 
mangled name instead of function name.


Is it useful idea?


you can do this yourself just with mixins and templates, but the 
real problem is c++ abi and name mangling. so you will need to do 
runtime search for c++ mangled names and which runtime used, get 
it and call placement new and ctor(with the help of asm{} of 
course), do the same for other operators. it is possible, but 
this is never be safe at least due to non-standardized name 
mangling.


you can write small library which would help doing this all if 
you really want this.


Re: C++ constructors, destructors and operator access

2013-05-20 Thread Daniel Murphy
Igor Stepanov wazar.leoll...@yahoo.com wrote in message 
news:pckdwxwvumenyzbuv...@forum.dlang.org...
 Yes, language shouldn't be modified for the sake of one goal.
 But do you think, that calling C++ constructors from D is not typical 
 task? I sure, that we must get a common way to bind C++ classes to D. No 
 templates, no exceptions. But operators and constructors/destructors is 
 needed. It may be special tool, that eat C++ header and return D file + 
 C++ glue file. This util should transform all fields and constructors to D 
 final methods for extern(C++) interface.
 In addition to this tool we can make a D binding layer, which simplify 
 typical operations such as creating C++ objects using ::operator new() (or 
 class operator new() if in exists) and destroying with  operator delete() 
 (local or global).


Mapping constructors is complicated...  Do they have the same semantics in 
both languages?  Both on the heap and on the stack?  Eg. how on earth do you 
map a default constructor for a struct?  Same problems with destructors. 
Which allocator do you use for the heap?  etc

Operator overloads are much worse, they just don't all map.  Do we support 
part of the set?  Or add the missing ones to D? eg comparison operators

 By the way: Why D disallow static __gshared C++ variables in classes? This 
 is a principled feature (if yes: why?) or omission?

It does?  Is this problem linux only?  I don't see any reason why it would 
be excluded on purpose.

That said, extern(C++) is mostly untested.  There are some truly awful bugs 
lurking if you try to use complicated types/declarations.  This is slowly 
improving. 




Re: C++ constructors, destructors and operator access

2013-05-20 Thread Igor Stepanov


Mapping constructors is complicated...  Operator overloads are 
much worse, they just don't all map.

You have misunderstood me.
I spoke out against the mapping. I spoke only about access.
For example if we automatically generate a binding extern(C++) 
interface we can add a special methods to access to operators and 
constructors/destructors.

For example:

С++:
class Foo
{
  int operator(const Foo);
  int operator(const Foo);
  int operator[](size_t);
  Foo();
  ~Foo();
};

D automatically generated interface:
extern(C++) interface Foo
{
  final int __operator_lt(const Foo);
  final int __operator_gt(const Foo);
  final ref int __operator_index(size_t);
  final void __constructor();
  final void __destructor();
}

Those operator-access methods shouldn't have operator semantic in 
D. If user want to use C++ __operator_lt for compare objects in 
D, him cat manually create opCmp method and use __operator_lt in 
it. But it is user task. I think, we should only provide access 
to operators and constructors methods.


About constructors:

In addition those methods we can add some information methods. 
For example size_t __sizeof() method which return size of this 
object. After this we can provide some allocate+constructor 
functions. For example:

auto foo = cppNewClass!Foo(args);

This template functions perform next actions:
1. Try to find overloaded operator new(). If overloaded new has 
been finded then cppNewClass will use it, otherwise cppNewClass 
will use default new.

2. Try to find constructor, which can called with specified args.
3. Allocate memory using __sizeof() method.
4. Call constructor over alloated memory.

for pair to cppNewClass can be provided cppDeleteClass function 
with same semantic.


This support layer will very simplify interface with C++ code.


By the way: Why D disallow static __gshared C++ variables in 
classes? This is a principled feature (if yes: why?) or 
omission?


It does?  Is this problem linux only?  I don't see any reason 
why it would

be excluded on purpose.
Ok. I've created pull request 
https://github.com/D-Programming-Language/dmd/pull/2053



That said, extern(C++) is mostly untested.  There are some 
truly awful bugs
lurking if you try to use complicated types/declarations.  This 
is slowly

improving.

I've bumped two old bugzilla issues about extern(C++)
http://d.puremagic.com/issues/show_bug.cgi?id=1687
http://d.puremagic.com/issues/show_bug.cgi?id=4620
Please comment it and close if they are invalid.



Re: C++ constructors, destructors and operator access

2013-05-20 Thread nazriel

On Monday, 20 May 2013 at 20:11:27 UTC, nazriel wrote:

On Saturday, 18 May 2013 at 22:23:51 UTC, Igor Stepanov wrote:
At the current time D have powerful mechanism of access to C++ 
classes.
For access to methods of C++ classes (virtual and not) we can 
use extern(C++) interface.


//С++

class CPPTest1
{
   int a;
   int b;
 public:
   virtual int boom();
   int fun();
   static int gun();
   CPPTest1(int);
   virtual ~CPPTest1();
   int operator[](size_t);
};

class CPPTest2: public CPPTest1
{
   int boom();
};

//D
extern(C++)interface CPPTest1
{
   int boom();
   static int gun();
   final int fun();
}

extern(C++)interface CPPTest2: CPPTest1
{
   //int boom();
}



As a rule, non-static fields are not public in C++ classes and 
is not part of interface. Thus the most of C++ classes can be 
bound without any glue c++ code.
However D dont support C++ overloaded operators and 
constructors. Yes, we cannot make mapping C++ operators to D 
operators and C++ constructors to D constructors). Nonetheless 
С++ operators and constructors are the simple C++ functions or 
methods with special mangling. Thus I've suggest next 
mechanism:
Allow special pragma(cppSymbol, string_arg), when string_arg 
is the name of c++ thing.

Example:

extern(C++)interface CPPTest1
{
   int boom();
   static int gun();
   final int fun();
   ///
   pragma(cppSymbol, constructor) final void ctor(int); 
//linked with CPPTest1(int);
   pragma(cppSymbol, destructor) void dtor(); //linked with 
virtual ~CPPTest1();
   pragma(cppSymbol, []) ref int indexOf(size_t); //linked 
with int operator[](size_t);

}

This pragma must apply to the function (or method), use 
natural C++ mangle, but set operatror or constructor or 
destructor mangled name instead of function name.


Is it useful idea?


Isn't it possible already with something like:

extern(C++) interface Foo
{
pragma(mangle, typeof(this).mangleof ~ 
generateCPPMangle!myOwnFunctionMangling) void foo();

}


Of course I mean:

extern(C++) interface Foo
{
pragma(mangle, generateCPPMangle!(typeof(this).mangleof, 
myOwnFunctionMangling)) void foo();

}


AFAIK, mangle pragma was merged recently.


Re: C++ constructors, destructors and operator access

2013-05-20 Thread nazriel

On Saturday, 18 May 2013 at 22:23:51 UTC, Igor Stepanov wrote:
At the current time D have powerful mechanism of access to C++ 
classes.
For access to methods of C++ classes (virtual and not) we can 
use extern(C++) interface.


//С++

class CPPTest1
{
int a;
int b;
  public:
virtual int boom();
int fun();
static int gun();
CPPTest1(int);
virtual ~CPPTest1();
int operator[](size_t);
};

class CPPTest2: public CPPTest1
{
int boom();
};

//D
extern(C++)interface CPPTest1
{
int boom();
static int gun();
final int fun();
}

extern(C++)interface CPPTest2: CPPTest1
{
//int boom();
}



As a rule, non-static fields are not public in C++ classes and 
is not part of interface. Thus the most of C++ classes can be 
bound without any glue c++ code.
However D dont support C++ overloaded operators and 
constructors. Yes, we cannot make mapping C++ operators to D 
operators and C++ constructors to D constructors). Nonetheless 
С++ operators and constructors are the simple C++ functions or 
methods with special mangling. Thus I've suggest next mechanism:
Allow special pragma(cppSymbol, string_arg), when string_arg is 
the name of c++ thing.

Example:

extern(C++)interface CPPTest1
{
int boom();
static int gun();
final int fun();
///
pragma(cppSymbol, constructor) final void ctor(int); 
//linked with CPPTest1(int);
pragma(cppSymbol, destructor) void dtor(); //linked with 
virtual ~CPPTest1();
pragma(cppSymbol, []) ref int indexOf(size_t); //linked 
with int operator[](size_t);

}

This pragma must apply to the function (or method), use natural 
C++ mangle, but set operatror or constructor or destructor 
mangled name instead of function name.


Is it useful idea?


Isn't it possible already with something like:

extern(C++) interface Foo
{
pragma(mangle, typeof(this).mangleof ~ 
generateCPPMangle!myOwnFunctionMangling) void foo();

}

AFAIK, mangle pragma was merged recently.


Re: C++ constructors, destructors and operator access

2013-05-20 Thread Igor Stepanov

On Monday, 20 May 2013 at 20:13:47 UTC, nazriel wrote:

On Monday, 20 May 2013 at 20:11:27 UTC, nazriel wrote:

On Saturday, 18 May 2013 at 22:23:51 UTC, Igor Stepanov wrote:
At the current time D have powerful mechanism of access to 
C++ classes.
For access to methods of C++ classes (virtual and not) we can 
use extern(C++) interface.


//С++

class CPPTest1
{
  int a;
  int b;
public:
  virtual int boom();
  int fun();
  static int gun();
  CPPTest1(int);
  virtual ~CPPTest1();
  int operator[](size_t);
};

class CPPTest2: public CPPTest1
{
  int boom();
};

//D
extern(C++)interface CPPTest1
{
  int boom();
  static int gun();
  final int fun();
}

extern(C++)interface CPPTest2: CPPTest1
{
  //int boom();
}



As a rule, non-static fields are not public in C++ classes 
and is not part of interface. Thus the most of C++ classes 
can be bound without any glue c++ code.
However D dont support C++ overloaded operators and 
constructors. Yes, we cannot make mapping C++ operators to D 
operators and C++ constructors to D constructors). 
Nonetheless С++ operators and constructors are the simple C++ 
functions or methods with special mangling. Thus I've suggest 
next mechanism:
Allow special pragma(cppSymbol, string_arg), when string_arg 
is the name of c++ thing.

Example:

extern(C++)interface CPPTest1
{
  int boom();
  static int gun();
  final int fun();
  ///
  pragma(cppSymbol, constructor) final void ctor(int); 
//linked with CPPTest1(int);
  pragma(cppSymbol, destructor) void dtor(); //linked with 
virtual ~CPPTest1();
  pragma(cppSymbol, []) ref int indexOf(size_t); //linked 
with int operator[](size_t);

}

This pragma must apply to the function (or method), use 
natural C++ mangle, but set operatror or constructor or 
destructor mangled name instead of function name.


Is it useful idea?


Isn't it possible already with something like:

extern(C++) interface Foo
{
   pragma(mangle, typeof(this).mangleof ~ 
generateCPPMangle!myOwnFunctionMangling) void foo();

}


Of course I mean:

extern(C++) interface Foo
{
pragma(mangle, generateCPPMangle!(typeof(this).mangleof, 
myOwnFunctionMangling)) void foo();

}


AFAIK, mangle pragma was merged recently.


If we'll implement generateCPPMangle template, we'll can do all:)
This way one of the possible. There are another way to do it. I 
don't know, what a best way now. But I think, this (simple 
binding C++ code to D) is important issue and we should solve it 
using one of the possible way.


Re: C++ constructors, destructors and operator access

2013-05-19 Thread Igor Stepanov

No.
Ok. As I know, there is running process to moving DMD front-end 
from C++ to D. As I remember, process expect to be gradual. Thus 
I the same moment will be C++ classes and D classes in the 
frontend. How you are planning create new C++ objects from D? Are 
you planning add to all classes special constructor static 
method, which will create new instances of C++ classes and return 
it, or you see another way to do it?




Re: C++ constructors, destructors and operator access

2013-05-19 Thread Iain Buclaw
On 19 May 2013 13:20, Igor Stepanov wazar.leoll...@yahoo.com wrote:

 No.

 Ok. As I know, there is running process to moving DMD front-end from C++
 to D. As I remember, process expect to be gradual. Thus I the same moment
 will be C++ classes and D classes in the frontend. How you are planning
 create new C++ objects from D? Are you planning add to all classes special
 constructor static method, which will create new instances of C++ classes
 and return it, or you see another way to do it?


All new'ing will be done in D.  The C++ glue-layer methods are a problem,
and we will be moving to using a visitor interface between the two.


-- 
Iain Buclaw

*(p  e ? p++ : p) = (c  0x0f) + '0';


Re: C++ constructors, destructors and operator access

2013-05-19 Thread Igor Stepanov
Is this mean, that D functions will _not_ create C++ objects with 
new?

For example:
You have moved parser to D, but you haven't moved expressions to 
D yet.
And you want to create new Expression object in parser (in D 
code), but Expression class defined in C++. What will you do in 
this case?


Re: C++ constructors, destructors and operator access

2013-05-19 Thread Daniel Murphy
Igor Stepanov wazar.leoll...@yahoo.com wrote in message 
news:wuevxraaffhaaceap...@forum.dlang.org...
 Is this mean, that D functions will _not_ create C++ objects with new?
 For example:
 You have moved parser to D, but you haven't moved expressions to D yet.
 And you want to create new Expression object in parser (in D code), but 
 Expression class defined in C++. What will you do in this case?

This is not how we're moving it.  The entire frontend will be moved in one 
go, there will never be a need to create a C++ class from D.

That said, the glue layer will remain in C++ and will need to create 
instances of classes defined in D.  The current glue layer calls 43 
different constructors.

I don't have a solution for this yet, but it will probably be:
a) Extend D to allow creating classes with constructors callable from C++
b) Create/generate factory functions for each class new'd in the glue layer
c) Remove all class allocations from the glue layer

I'm leaning towards b, or maybe c, and I think you should too. 




Re: C++ constructors, destructors and operator access

2013-05-19 Thread Igor Stepanov

On Sunday, 19 May 2013 at 13:56:56 UTC, Daniel Murphy wrote:

Igor Stepanov wazar.leoll...@yahoo.com wrote in message
news:wuevxraaffhaaceap...@forum.dlang.org...
Is this mean, that D functions will _not_ create C++ objects 
with new?

For example:
You have moved parser to D, but you haven't moved expressions 
to D yet.
And you want to create new Expression object in parser (in D 
code), but Expression class defined in C++. What will you do 
in this case?


This is not how we're moving it.  The entire frontend will be 
moved in one

go, there will never be a need to create a C++ class from D.

That said, the glue layer will remain in C++ and will need to 
create
instances of classes defined in D.  The current glue layer 
calls 43

different constructors.

I don't have a solution for this yet, but it will probably be:
a) Extend D to allow creating classes with constructors 
callable from C++
b) Create/generate factory functions for each class new'd in 
the glue layer

c) Remove all class allocations from the glue layer

I'm leaning towards b, or maybe c, and I think you should too.


Yes, language shouldn't be modified for the sake of one goal.
But do you think, that calling C++ constructors from D is not 
typical task? I sure, that we must get a common way to bind C++ 
classes to D. No templates, no exceptions. But operators and 
constructors/destructors is needed. It may be special tool, that 
eat C++ header and return D file + C++ glue file. This util 
should transform all fields and constructors to D final methods 
for extern(C++) interface.
In addition to this tool we can make a D binding layer, which 
simplify typical operations such as creating C++ objects using 
::operator new() (or class operator new() if in exists) and 
destroying with  operator delete() (local or global).


By the way: Why D disallow static __gshared C++ variables in 
classes? This is a principled feature (if yes: why?) or omission?


Re: C++ constructors, destructors and operator access

2013-05-18 Thread Ali Çehreli

On 05/18/2013 03:23 PM, Igor Stepanov wrote:

 natural C++ mangle

That's part of the problem: C++ name mangling is not standardized.

Ali



Re: C++ constructors, destructors and operator access

2013-05-18 Thread Igor Stepanov

On Saturday, 18 May 2013 at 22:55:34 UTC, Ali Çehreli wrote:

On 05/18/2013 03:23 PM, Igor Stepanov wrote:

 natural C++ mangle

That's part of the problem: C++ name mangling is not 
standardized.


Ali


But D compilers are using C++ mangle for extern(C++) functions 
now.
I think, this trouble can be solved in a glue layer of compiler. 
Now, on posix we can use gcc c++ mangle, on windows - dmc/visual 
c++ mangle.

As I know, there is not many kinds of c++ mangle. over 10:)
Current implementation use only two: dmc for windows, gcc for 
posix. If another back-end will be added, we can add another 
mangle support.
I think, C++ to D binding is a very important issue. If D will 
provide good mechanism of binding, some projects will can be 
simple moved to D and some project leaders will can choose D to 
develop his projects.


Re: C++ constructors, destructors and operator access

2013-05-18 Thread Iain Buclaw
On May 18, 2013 11:25 PM, Igor Stepanov wazar.leoll...@yahoo.com wrote:

 At the current time D have powerful mechanism of access to C++ classes.
 For access to methods of C++ classes (virtual and not) we can use
extern(C++) interface.

 //С++

 class CPPTest1
 {
 int a;
 int b;
   public:
 virtual int boom();
 int fun();
 static int gun();
 CPPTest1(int);
 virtual ~CPPTest1();
 int operator[](size_t);
 };

 class CPPTest2: public CPPTest1
 {
 int boom();
 };

 //D
 extern(C++)interface CPPTest1
 {
 int boom();
 static int gun();
 final int fun();
 }

 extern(C++)interface CPPTest2: CPPTest1
 {
 //int boom();
 }



 As a rule, non-static fields are not public in C++ classes and is not
part of interface. Thus the most of C++ classes can be bound without any
glue c++ code.
 However D dont support C++ overloaded operators and constructors. Yes, we
cannot make mapping C++ operators to D operators and C++ constructors to D
constructors). Nonetheless С++ operators and constructors are the simple
C++ functions or methods with special mangling. Thus I've suggest next
mechanism:
 Allow special pragma(cppSymbol, string_arg), when string_arg is the name
of c++ thing.
 Example:

 extern(C++)interface CPPTest1
 {
 int boom();
 static int gun();
 final int fun();
 ///
 pragma(cppSymbol, constructor) final void ctor(int); //linked with
CPPTest1(int);
 pragma(cppSymbol, destructor) void dtor(); //linked with virtual
~CPPTest1();
 pragma(cppSymbol, []) ref int indexOf(size_t); //linked with int
operator[](size_t);
 }

 This pragma must apply to the function (or method), use natural C++
mangle, but set operatror or constructor or destructor mangled name instead
of function name.

 Is it useful idea?

No.

Regards
-- 
Iain Buclaw

*(p  e ? p++ : p) = (c  0x0f) + '0';