Thread overview
Fwd: Interfacing with C++
Nov 03, 2014
Shriramana Sharma
Nov 03, 2014
Daniel Murphy
Nov 04, 2014
Shriramana Sharma
Nov 04, 2014
Kagamin
Re: Interfacing with C++
Nov 06, 2014
Daniel Murphy
Nov 03, 2014
Abdulhaq
Nov 03, 2014
Abdulhaq
Nov 05, 2014
albatroz
Nov 05, 2014
Abdulhaq
Nov 03, 2014
deadalnix
November 03, 2014
It was recommended that I discuss this on this list rather than d.learn... (I didn't think I'd graduate out of d.learn *that* quickly...)

---------- Forwarded message ----------

Hello. I really really need to be able to interface well with a C++ library which contains lots of classes if I am going to further invest time into D.

Now from the http://dlang.org/cpp_interface I find out the current status of built-in C++ interfacing support. I'm working on Linux so using the COM support is not an option for me (whatever COM may be!).

A few queries:

1) How mature is the SWIG support for wrapping a library into D? Specifically does the above SWIG support take advantage of the built-in C++ support features like connecting directly to virtual functions?

2) Is there any further work underway to implement support for static and non-virtual class member functions? Or is this not at all possible? If so, why?

3) The page speaks about having to integrate an entire C++ compiler into the D compiler. Could the usage of libclang help here in having to avoid writing a new C++ compiler module or am I talking through my (non-existent) hat?

--
Shriramana Sharma ஶ்ரீரமணஶர்மா श्रीरमणशर्मा

November 03, 2014
"Shriramana Sharma via Digitalmars-d"  wrote in message news:mailman.1464.1415039051.9932.digitalmars-d@puremagic.com...

> Hello. I really really need to be able to interface well with a C++
> library which contains lots of classes if I am going to further invest
> time into D.
>
> Now from the http://dlang.org/cpp_interface I find out the current
> status of built-in C++ interfacing support. I'm working on Linux so
> using the COM support is not an option for me (whatever COM may be!).

That page is out of date.  Support has improved significantly since then.

> A few queries:
>
> 1) How mature is the SWIG support for wrapping a library into D?
> Specifically does the above SWIG support take advantage of the
> built-in C++ support features like connecting directly to virtual
> functions?

No idea.

> 2) Is there any further work underway to implement support for static
> and non-virtual class member functions? Or is this not at all
> possible? If so, why?

Work is complete.  IIRC it was in the last release, you might need to grab master/an alpha for very latest stuff.  Special member functions (dtor/operators) generally don't work.

> 3) The page speaks about having to integrate an entire C++ compiler
> into the D compiler. Could the usage of libclang help here in having
> to avoid writing a new C++ compiler module or am I talking through my
> (non-existent) hat?

Yes.  But adding a second compiler to the compiler is problematic even if you don't have the write the second compiler.  You however could make a C++ binding generator with clang (see dstep).

Also, note that you can still use some aspects of C++ templates from D - you can pass a templated struct or class between the languages (but you will have to more or less re-write it on the other side).  This is done in ddmd (magicport2/newmagic) with root.array.

You can also call templated functions with some hacks, if you are careful about ensuring they're instantiated on the C++ side.  (ie use pragma(mangle))

So, a lot is possible, but when things go wrong you'll be fighting nasty abi and alignment bugs. 

November 03, 2014
On Monday, 3 November 2014 at 18:24:12 UTC, Shriramana Sharma via
Digitalmars-d wrote:
> It was recommended that I discuss this on this list rather than
> d.learn... (I didn't think I'd graduate out of d.learn *that*
> quickly...)
>
> ---------- Forwarded message ----------
>
> Hello. I really really need to be able to interface well with a C++
> library which contains lots of classes if I am going to further invest
> time into D.
>

You might find my project Smidgen
(https://github.com/alynch4047/smidgen) useful, It's not finished
but you might consider extending it rather than starting
elsewhere. The build systems works on Linux 64 using cmake so you
should be able to get started fairly easily, and there is a
sample mini set of C++ classes used for testing which you can
look at.  It was created to wrap Qt, using the same *.sip file
definitions as are used by PyQt. The FEATURE list TODO and DONE
list is as follows:

FEATURES
========
* All D
* Understandable, maintainable code
* Wraps protected and virtual methods, allows virtual methods to
be overridden in D
* Mixin classes in target C++ library supported
* Allows custom type conversions between C++ and D types
* C++ enums mapped to D enums and are type checked in D
* Wraps nested C++ classes
* Tested
* Based on the sip format. This is well proven and allows
simplified maintenance of wrappers for multiple versions of the
target library. (All larger target libraries will need some
ongoing maintenance of the wrapper regardless of the wrapping
technology).

PROVISOS
========
* Currently works with wrapped method arguments/return types of
X, X* and X&
but not implemented are X*& etc.
* Wrapped types which are returned by value must have a copy
constructor (could be changed later)
* DO NOT capture references to (stack-based) arguments when
overriding wrapped
virtual methods. They are destroyed by the wrapper when the
virtual method ends.
* (Qt only) When emitting signals, must use emit! notation, not
just call signal.

GOTCHAS
=======
* An invalid getClassNameC can cause segfaults when compiling the
target application because it is used in template instantiation
* If getClassName does not work for a subclass (QMoveEvent) when
we are expecting T = the base class (QEvent),
and it was created as the base class (QEvent) (because
getClassName did not work) then it casts
to the sub class (QMOveEvent) on a later lookup (because it is
defined on the
other method as the return type) and crashes.

DONE
====
* Static methods
* Default values
* Enums
* Multiple packages / modules
* Nested classes e.g. QMetaObject::Connection
* Transfer, TransferThis and TransferBack for arguments
* Destructors - and deregister instance from createdInD
* Multiple inheritance => multiple pointers
* Conversion functions in package_wrapper.cpp should have ability
to add #include directives
at the top of package_wrapper.cpp
* Virtual functions
* Protected functions
* Sip If clauses for features, platforms

TODO
====
* non-primitive Typedefs
* Primitive types C -> D conversion
- *.conf file
%CToDType long = long
%CToDType unsigned char = ubyte
* Sip If clauses for timelines
%Timeline {Qt_5_0_0 Qt_5_0_1 Qt_5_0_2}
* KeepReference for arguments + tests for Transfer etc. - Easy,
in class with KeepRef
e.g. View.setModel(model /KeepReference/) it has an extra
attribute
- void* setModel_SMIKeepRef
then in setModel() {
View_setModel_SMIX23(model.wrappedObject);
setModel_SMIKeepRef = model;
}
This will make D keep a reference to the model as long as the
View instance is alive.
Each view will have its own reference so the total can go above 1
for a given model.
* getCastPointerForInterface can be easily improved by not
switching on a name but instead
each class has a separate variable for each base class pointer,
that is populated in
the constructor
- each class has one extra pointer per interface implemented
- override virtual void*[] getExtraPointers() {
void*[] extraPointers = super.getExtraPointers();
extraPointers ~= wrappedObject_Calculator;
return extraPointers;
}
- in constructor this() {
wrappedObject_Calculator = castRectAsCalculator(wrappedObject);
}
- in destructor ~this() {
deregisterWrappedObject(wrappedObject);
deregisterWrappedObejct(wrappedObject_Calculator);
}
* instance_wrapper et al., need to also register base class
pointers
* getWrappedObject / getClassName - how to handle this in a
x-module fashion.
* Add support for wrapping members
* Add QTest support
* int arguments that take a default enum value & enum defaults
* char** -> Use this _idea_
this(string[] args)
{
// if (m_instance != null)
// throw new RuntimeException("QCoreApplication can only be
initialized once");
argc = cast(int)args.length;
argv = toStringzArray(args);
this(&argc, argv);
// m_instance.aboutToQuit.connect(m_instance,
"disposeOfMyself()");
}
* Threading? - wrappedObjects[] should be shared as with CPP
instance tracker. Use signal.d's
WeakRef and InvisibleAddress
* qRegisterMetaType??
* Add %UsesConverter to package.sip, so that the correct includes
are in the package and
we don't get problems trying to include e.g. widget.h in core.so
* Converted types that are returned are not passed through
getWrapper - might cause
duplicate D objects around same C++ object e.g. QList<QWidget>?
Is this a problem?
* In CPP wrapper, the conversion from argument can have a memory
leak (e.g. new string created
and not deleted) BETTER - pass new type in as a reference if
possible
* Enums don't have C++ value if it was specified - need a CPP
program that writes
a text file e.g. Color::Red 124
Color::Green 234
and then write enum wrappers which include the values using the
text lookup (at build time
of wrapper NOT at runtime of final program)
* Operator overloading - do nicely in D
* Free function operator overloads in CPP
* Handle array arguments
* Multiple inheritance - if a method returns an instance of an
interface and it has
been created by CPP then the *Impl is returned - it is not
currently typechecked.
We should instead check if it's already on a registered object.
* Interfaces - allow virtual calls on the interface
* Lifetime management - VTK?
* VTK/ Qt differences - have factory methods for Method, Klass,
Package etc., and
different wrapping flavours can have differing factories. Needs
API stability.
* Virtual functions, overloading etc. - will the right call be
made if from an inherited class I make a call
on an inherited D class method for a virtual method - will it
call the C++ base equivalent,
thereby not calling the correct virtual call on the derived
class? See GOTW 5,
calling virtual funcs on a base pointer will not call the derived
class method.
* Answer to above Q - yes, so need to implement wrappers for all
inherited virtual functions
even if not mentioned in SIP file
* Signals and slots
* Enums declared inside classes
* In CPP wrapper class remove factory function/private
constructor - it is not reqd.
* Nested classes and multiple inheritance combination probably
not working (e.g. Klass.getWrappedClassName)





November 03, 2014
On Monday, 3 November 2014 at 20:32:34 UTC, Abdulhaq wrote:
> On Monday, 3 November 2014 at 18:24:12 UTC, Shriramana Sharma via
> Digitalmars-d wrote:
>> It was recommended that I discuss this on this list rather than
>> d.learn... (I didn't think I'd graduate out of d.learn *that*
>> quickly...)
>>
>> ---------- Forwarded message ----------
>>
>> Hello. I really really need to be able to interface well with a C++
>> library which contains lots of classes if I am going to further invest
>> time into D.
>>
>
> You might find my project Smidgen
> (https://github.com/alynch4047/smidgen) useful, It's not finished
> but you might consider extending it rather than starting
> elsewhere. The build systems works on Linux 64 using cmake so you
> should be able to get started fairly easily, and there is a
> sample mini set of C++ classes used for testing which you can
> look at.  It was created to wrap Qt, using the same *.sip file
> definitions as are used by PyQt. The FEATURE list TODO and DONE
> list is as follows:
>

BTW one of the reasons that I have not yet completed this project is that I don't have a handle on where the current C++ interfacing work is going and don't want to work on something only to have it made redundant. Also, it has to use a hack to work around the lack of weak references and if the GC is changed to relocate objects then it will break this aspect of the code.
November 03, 2014
On Monday, 3 November 2014 at 18:24:12 UTC, Shriramana Sharma via Digitalmars-d wrote:
> 1) How mature is the SWIG support for wrapping a library into D?
> Specifically does the above SWIG support take advantage of the
> built-in C++ support features like connecting directly to virtual
> functions?
>

I investigated this recently. It actually work fairly well, minus 2 things:
 - swig use 0 terminated sting to pass string back en forth. But in C++, char* can be a string or a buffer, and when it is the later, you can run into problems.
 - swig generate unnecessary garbage in the binding layer.

I tried to work on it, but swig require serious ramp up to contribute to.

November 04, 2014
On 11/4/14, Daniel Murphy via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>> Now from the http://dlang.org/cpp_interface I find out the current status of built-in C++ interfacing support. I'm working on Linux so using the COM support is not an option for me (whatever COM may be!).
>
> That page is out of date.  Support has improved significantly since then.
>
>> 2) Is there any further work underway to implement support for static and non-virtual class member functions? Or is this not at all possible? If so, why?
>
> Work is complete.  IIRC it was in the last release, you might need to grab master/an alpha for very latest stuff.  Special member functions (dtor/operators) generally don't work.

So I'm using latest dmd 2.066.1 on an i386 machine. Does it have the latest functionality which you refer to? And what is the syntax to support static and non-virtual member functions?

Thanks!

-- 
Shriramana Sharma ஶ்ரீரமணஶர்மா श्रीरमणशर्मा

November 04, 2014
Static functions correspond to static D functions. Non-virtual functions are struct methods and final class methods.
November 05, 2014
On Monday, 3 November 2014 at 20:32:34 UTC, Abdulhaq wrote:

> You might find my project Smidgen
> (https://github.com/alynch4047/smidgen) useful, It's not finished
> but you might consider extending it rather than starting
> elsewhere.

woe...
The first time I see this project mentioned.
You may consider publishing this in the announcement forum, it will give it more visibility, it looks very promising.

And now to play with it...

Thank you
November 05, 2014
On Wednesday, 5 November 2014 at 12:39:16 UTC, albatroz wrote:
> On Monday, 3 November 2014 at 20:32:34 UTC, Abdulhaq wrote:
>
>> You might find my project Smidgen
>> (https://github.com/alynch4047/smidgen) useful, It's not finished
>> but you might consider extending it rather than starting
>> elsewhere.
>
> woe...
> The first time I see this project mentioned.
> You may consider publishing this in the announcement forum, it will give it more visibility, it looks very promising.
>
> And now to play with it...
>
> Thank you

Please ask me any questions direct to alynch4047@gmail.com, I'll do my best to help you. You might be interested in my progress in wrapping Qt which can be seen at https://github.com/alynch4047/sqt . The example Qt wrapped program simply wraps a QLineEdit and overrides various virtual methods, however most of the *.sip format is implemented for D and I could probably wrap a fair amout of Qt now, but again it's on hold ATM.

Please do let me know how you get on, even if it doesn't work for you!
November 06, 2014
"Shriramana Sharma via Digitalmars-d"  wrote in message news:mailman.1515.1415110123.9932.digitalmars-d@puremagic.com...

> So I'm using latest dmd 2.066.1 on an i386 machine. Does it have the
> latest functionality which you refer to? And what is the syntax to
> support static and non-virtual member functions?

I think so.  Just declare a static or final function in an extern(C++) class or a static/normal function in an extern(C++) struct.