how to catch D Throwables (or exceptions) from C++?

Rémy Mouëza via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Thu Dec 1 11:56:26 PST 2016


On Thursday, 1 December 2016 at 01:58:13 UTC, Timothee Cour wrote:
> eg:
>
> ```
> dlib.d:
> extern(C) void dfun(){assert(0, "some_msg");}
>
> clib.cpp:
> extern "C" void dfun();
> void fun(){
>   try{
>     dfun();
>   }
>   catch(...){
>     // works but how do i get "some_msg" thrown from D?
>   }
> }
> ```

I had the a similar problem when writing bindings to the RtMidi 
library back in 2013.
I opted for catching C++ exceptions in C++, wrap the functions in 
a C API; the C API returns a special type that contains a status, 
a result and an error message.
On the D side, when a status is false, a D exception is raised, 
mirroring the one that was caught in C++.
This strategy is described in dconf 2014:
https://www.youtube.com/watch?v=1JZNvKhA3mA&t=20m45s

It should be working the other way arround: catch a D exception 
in D, return a wrapped value: on the C++ side, if the wrapped 
value status is false, throw an exception

Below is an sample of the code I wrote:

In C++:
```
* Special return type.
  * - success is true when a call went right,
  *           is false when an exception occured.
  * - errMsg can be used to throw a D exception.
  * - value is the value to be returned from a call.
  */
template <typename T>
struct answer {
     int success;
     T value;
     const char * errMsg;
};

* Predefined types of return for RtMidi. */
typedef answer<RtMidiIn *> answerRtMidiIn_p;
typedef answer<RtMidiOut *> answerRtMidiOut_p;
typedef answer<bool> answerBool;
typedef answer<const char *> answerConstChar_p;
typedef answer<double> answerDouble;

answerRtMidiIn_p RtMidiIn_new (
         int api,
         char * clientName,
         unsigned int queueSizeLimit)
{
     RtMidiIn * ptr;

     try {
         const std::string name = std::string (clientName);
         ptr = new RtMidiIn ((RtMidi::Api) api, name, 
queueSizeLimit);
         answerRtMidiIn_p ans = {true, ptr, ""};
         return ans;

     } catch (RtError & error) {
         answerRtMidiIn_p ans = {false, 0, error.getMessage 
().c_str ()};
         return ans;
     }
}
```

in D:
```
/* Special return type.
  * - success is true when a call went right,
  *           is false when an exception occured.
  * - errMsg can be used to throw a D exception.
  * - value is the value to be returned from a call.
  */
struct answer (T) {
     int success;
     T value;
     const (char) * errMsg;
}

extern (C) {
     // ...
     answer!(void *) RtMidiIn_new (
                         int api,
                         immutable(char) * clientName,
                         uint queueSizeLimit);
     // ...
}

class RtMidiIn {
     // Pointer to the C++ class, package visibility.
     protected void * ptr;

     public:

     this (
             int api = UNSPECIFIED,
             string clientName = "RtMidi Input Client",
             uint queueSizeLimit = 100)
     {
         answer!(void *) ans
             = RtMidiIn_new (api,
                             clientName.toStringz,
                             queueSizeLimit);

         if (! ans.success)
             throw new RtError (ans.errMsg.to!string);

         this.ptr = ans.value;
     }

     // ...
}
```




More information about the Digitalmars-d-learn mailing list