www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - I want an exception message but my threaded callback just dies or

reply Markus <fmmbj protonmail.com> writes:
Hi, when you use core.windows and LoadLibrary to load a DLL, and 
that DLL will create a new thread and inside that it will call 
back into your D app, is there something to special to be aware 
of?

I've done it like with the CreateWindow and WndProc, but this 
time I'm loading a compiled portaudio DLL and I give it a call 
back. And I try to catch errors, but no matter what D Exception 
(I tried out of range and null dereferencing) that thread seems 
to either die silently (no hints in my console) or somehow fail 
to make portaudio go on calling (I don't think so).

I just wanted to ask if you know any pitfall with this... I'll go 
on using windbg and looking at things. I guess I should post a 
complete project, but I have to clean it up, and you maybe don't 
want to execute that portaudio32bit.dll from some unknown github 
account.

The function for Portaudio looks like that:

extern(C) nothrow int patestCallback(
	const void* inputBuffer,
	void* outputBuffer,
	uint framesPerBuffer,
	const PaStreamCallbackTimeInfo* timeInfo,
	PaStreamCallbackFlags statusFlags,
	void* userData)
{
	auto data = cast(paTestData*)userData;
	auto out_ = cast(float*)outputBuffer;

	auto ce = collectException(
		data.callback(
			data.frames_per_buffer,
			&data.left_buf[0],
			&data.right_buf[0]));
	if(ce !is null)
	{
		assumeWontThrow(writeln(ce.toString));
		TerminateProcess(GetCurrentProcess(), 0);		
	} else
	{
		assumeWontThrow(writeln("ce is null"));
	}
	
	for(uint i = 0; i < framesPerBuffer; ++i)
	{
		*out_++ = data.left_buf[i];
		*out_++ = data.right_buf[i];
	}

	return PaStreamCallbackResult.paContinue;
}

...
...

I give it to Portaudio like that

	{ auto err = Pa_OpenStream(
		&stream,
		null,
		&outputParameters,
		frames_per_second,
		frames_per_buffer,
		paClipOff,
		&patestCallback,
		&data);
Jun 10 2019
parent reply Markus <fmmbj protonmail.com> writes:
I have cleaned it up, kind of. Just in case you want to compile 
it. The Zip contains some DLL from 
https://github.com/spatialaudio/portaudio-binaries where you can 
find the original if you want.

https://gofile.io/?c=NpUxrJ

I'm in general thinking of buying a Mac. I know it has not much 
to do with this, but debugging Swift code in Xcode must be so 
"gorgeous" as they say.
Jun 10 2019
parent Markus <fmmbj protonmail.com> writes:
On Tuesday, 11 June 2019 at 05:15:17 UTC, Markus wrote:
 I have cleaned it up, kind of. Just in case you want to compile 
 it. The Zip contains some DLL from 
 https://github.com/spatialaudio/portaudio-binaries where you 
 can find the original if you want.

 https://gofile.io/?c=NpUxrJ

 I'm in general thinking of buying a Mac. I know it has not much 
 to do with this, but debugging Swift code in Xcode must be so 
 "gorgeous" as they say.
1) So, I've made it work. Using a global in the test.d for sharing between threads was no good idea it seems. It's just that I tend to do it because you will not end up passing arguments so much. But the shared keyword forced me to add D-atomic code, so I gave that up early and made it passing (borrowing?) the context/custom-data as argument, not being in global scope. 2) Second thing is, I removed collectException, because I was unable to do with it what it seems to be good for. I replaced it with another function call to a function that uses a try block, and assumeNoThrow goes around that function call. I'm a bit confused but it works (can print Exceptions). :) The changes look like this: test.d: auto stream = start_portaudio(44100, 512, &on_audio_buffer,cast(void*)sine_sound); // 1) pass around sine_sound, or anything that looks like a global portaudio.d: void on_audio_buffer_2(int frames, float* left, float* right, paTestData* data) { // 2) try { data.callback( data.frames_per_buffer, &data.left_buf[0], &data.right_buf[0], data.mydata); } catch(Throwable e) { writefln("e==%s",e.toString); TerminateProcess(GetCurrentProcess(), 0); } } extern(C) nothrow int patestCallback(........) { // 2) call the function that uses the try block assumeWontThrow( on_audio_buffer_2( data.frames_per_buffer, &data.left_buf[0], &data.right_buf[0], data)); }
Jun 12 2019