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;
    }

    // ...
}
```


Reply via email to