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

2016-12-02 Thread Elie Morisse via Digitalmars-d-learn

On Friday, 2 December 2016 at 08:13:51 UTC, Jacob Carlborg wrote:
On 2016-12-01 02:58, Timothee Cour via Digitalmars-d-learn 
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?
  }
}
```


At least for a C++ exception it's possible to get the current 
exception with __cxxabiv1::__cxa_current_primary_exception(). I 
verified and it works for C++ exceptions. I would think that 
the following works for D exceptions, but I cannot even catch 
the D exception in C++. Maybe it's not working properly on 
macOS.


// c++
void foo();
const char* getExceptionMessage(void*);

void bar()
{
try
{
foo();
}
catch(...)
{
void* e = __cxxabiv1::__cxa_current_primary_exception();
if (e)
{
const char* msg = getExceptionMessage(e);
if (msg)
printf("%s\n", msg);
else
printf("no message\n");
}
else
{
printf("no exception\n");
}
}
}

// d

extern(C++) void foo()
{
throw new Exception("foo");
}

extern(C++) immutable(char)* getExceptionMessage(void* e)
{
if (e)
{
auto t = cast(Throwable) e;
return t.msg.ptr;
}

return null;
}

I'm compiling the C++ code with clang++ and I need to link with 
libc++abi.


Exceptions thrown from D set a different exception class in the 
header, and the C++ personality routine (i.e the function that 
gets called for each catch block) only handles exceptions which 
displays the C++ exception class, so let D exceptions slip 
through.


To catch exceptions thrown by D code in C++ I think this would 
have to be done by throwing a C++ exception (eventually wrapping 
a D class), but this is yet to be implemented.


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

2016-12-02 Thread Jacob Carlborg via Digitalmars-d-learn

On 2016-12-01 02:58, Timothee Cour via Digitalmars-d-learn 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?
  }
}
```


At least for a C++ exception it's possible to get the current exception 
with __cxxabiv1::__cxa_current_primary_exception(). I verified and it 
works for C++ exceptions. I would think that the following works for D 
exceptions, but I cannot even catch the D exception in C++. Maybe it's 
not working properly on macOS.


// c++
void foo();
const char* getExceptionMessage(void*);

void bar()
{
try
{
foo();
}
catch(...)
{
void* e = __cxxabiv1::__cxa_current_primary_exception();
if (e)
{
const char* msg = getExceptionMessage(e);
if (msg)
printf("%s\n", msg);
else
printf("no message\n");
}
else
{
printf("no exception\n");
}
}
}

// d

extern(C++) void foo()
{
throw new Exception("foo");
}

extern(C++) immutable(char)* getExceptionMessage(void* e)
{
if (e)
{
auto t = cast(Throwable) e;
return t.msg.ptr;
}

return null;
}

I'm compiling the C++ code with clang++ and I need to link with libc++abi.

--
/Jacob Carlborg


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

2016-12-01 Thread Rémy Mouëza via Digitalmars-d-learn

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=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 
struct answer {
int success;
T value;
const char * errMsg;
};

* Predefined types of return for RtMidi. */
typedef answer answerRtMidiIn_p;
typedef answer answerRtMidiOut_p;
typedef answer answerBool;
typedef answer answerConstChar_p;
typedef answer 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;
}

// ...
}
```




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

2016-11-30 Thread Nicholas Wilson via Digitalmars-d-learn

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?
  }
}
```


portably not sure, but if you're using dwarf / libunwind you can 
probably use the API directly and get a pointer to the exception 
object and dereference a field of it's (i.e. p+ 
Throwable.msg.offsetof ).


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

2016-11-30 Thread Timothee Cour via Digitalmars-d-learn
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?
  }
}
```