www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Calling a C++ Object from D

reply "David Eagen" <spam_me_here mailinator.com> writes:
I'm trying to understand how to call a C++ library from D. Specifically,
the Windows Update API.

My goal is rather simple in that I want to detect whether there is a
reboot pending for the system. To do that I need to call the
ISystemInformation::RebootRequired property but I don't know how to do
that in D. Information about the call is at
http://msdn.microsoft.com/en-us/library/aa386098(v=vs.85).aspx.

I have the C++ header and have successfully defined VARIANT_BOOL,
VARIANT_TRUE, and VARIANT_FALSE. The last bit to do is to define the
ISystemInterface object itself and the RebootRequired method. How do I do
that?

-Dave
Jan 24 2012
next sibling parent reply "Dejan Lekic" <dejan.lekic gmail.com> writes:
Unfortunately, you cant use C++ namespaces. More about 
interfacing to C++ here: http://www.dlang.org/cpp_interface.html .

The easiest way to solve this is to write a C function that will 
glue your code with the C++ library.
Jan 24 2012
parent reply Richard Webb <webby beardmouse.org.uk> writes:
I've never used the Windows update API, but isn't it a COM interface rather
than a
C++ interface? You can call those directly from D.
Jan 24 2012
parent Richard Webb <webby beardmouse.org.uk> writes:
How about something like this (using Juno):

///////////////////////
import juno.com.core, std.stdio;

abstract final class SystemInformation {
  mixin(uuid("C01B9BA0-BEA7-41BA-B604-D0A36F469133"));
  mixin Interfaces!(ISystemInformation);
}

interface ISystemInformation : IDispatch
{
  mixin(uuid("ade87bf7-7b56-4275-8fab-b9b0e591844b"));

  int get_OemHardwareSupportLink(wchar* retval);
  int get_RebootRequired(out VARIANT_BOOL retval);
};

void main()
{
  //auto systemInformation =
coCreate!(ISystemInformation)(uuidof!(SystemInformation));
  auto systemInformation = SystemInformation.coCreate!ISystemInformation;

  if (systemInformation !is null)
  {
      scope(exit) tryRelease(systemInformation);

      VARIANT_BOOL b;
      int result = systemInformation.get_RebootRequired(b);

      if (SUCCEEDED(result))
      {
	  writefln("Reboot Required: %s", b);
      }
  }
}
///////////////////////
Jan 24 2012
prev sibling next sibling parent "Zachary Lund" <admin computerquip.com> writes:
On Tuesday, 24 January 2012 at 12:30:26 UTC, David Eagen wrote:
 I'm trying to understand how to call a C++ library from D. 
 Specifically,
 the Windows Update API.

 My goal is rather simple in that I want to detect whether there 
 is a
 reboot pending for the system. To do that I need to call the
 ISystemInformation::RebootRequired property but I don't know 
 how to do
 that in D. Information about the call is at
 http://msdn.microsoft.com/en-us/library/aa386098(v=vs.85).aspx.

 I have the C++ header and have successfully defined 
 VARIANT_BOOL,
 VARIANT_TRUE, and VARIANT_FALSE. The last bit to do is to 
 define the
 ISystemInterface object itself and the RebootRequired method. 
 How do I do
 that?

 -Dave

From what I understand, the most reliable way currently is to wrap the C++ API in a C API and then call the C API from D. It's easy but time consuming and can't be generated currently.
Jan 24 2012
prev sibling parent "David Eagen" <spam_me_here mailinator.com> writes:
On Tue, 24 Jan 2012 07:22:46 -0600, Richard Webb <webby beardmouse.org.uk>  
wrote:

 How about something like this (using Juno):

 ///////////////////////
 import juno.com.core, std.stdio;

 abstract final class SystemInformation {
   mixin(uuid("C01B9BA0-BEA7-41BA-B604-D0A36F469133"));
   mixin Interfaces!(ISystemInformation);
 }

 interface ISystemInformation : IDispatch
 {
   mixin(uuid("ade87bf7-7b56-4275-8fab-b9b0e591844b"));

   int get_OemHardwareSupportLink(wchar* retval);
   int get_RebootRequired(out VARIANT_BOOL retval);
 };

 void main()
 {
   //auto systemInformation =
 coCreate!(ISystemInformation)(uuidof!(SystemInformation));
   auto systemInformation = SystemInformation.coCreate!ISystemInformation;

   if (systemInformation !is null)
   {
       scope(exit) tryRelease(systemInformation);

       VARIANT_BOOL b;
       int result = systemInformation.get_RebootRequired(b);

       if (SUCCEEDED(result))
       {
 	  writefln("Reboot Required: %s", b);
       }
   }
 }
 ///////////////////////

Thank you very much. This works great. Yes, it turns out I was mistaken and this is COM and not C++. Juno definitely helps here. I cloned it from github and was glad to see that work had recently been done on Juno as well. -Dave
Jan 24 2012