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