Thread overview | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
August 28, 2017 C callbacks getting a value of 0! Bug in D? | ||||
---|---|---|---|---|
| ||||
Trying to set a callback for portaudio and it's seeing zero for the value passed. Pa_OpenStream(&stream, input, output, sampleRate, cast(ulong)0, cast(PaStreamFlags)(PaStreamFlags.NoFlag + 0*PaStreamFlags.PrimeOutputBuffersUsingStreamCallback), cast(PaStreamCallback)(a,b,c,d,e,f){ callbackCalled = true; return 0; }, null); I am using a debug build of portaudio that prints out all the parameters before anything else, so it's not an issue with portaudio. I've tried passing a normal function: __gshared int sawtooth(const(void)* inputBuffer, void* outputBuffer, ulong framesPerBuffer, const(PaStreamCallbackTimeInfo)* timeInfo, PaStreamCallbackFlags statusFlags, void *userData) { return 0; } and passing it as &sawtooth. with the same issue. I've tried changing the calling convention and using __gshared but the value is always 0. It seems other values are 0 too and can't seem to get any value in to the callback(Even a random one). The output essentially always looks like this: Opening Stream! Pa_OpenStream called: PaStream** stream: 0x00823EA0 PaStreamParameters *inputParameters: NULL PaStreamParameters *outputParameters: 0x02C6C1C0 PaDeviceIndex outputParameters->device: 3 int outputParameters->channelCount: 4 PaSampleFormat outputParameters->sampleFormat: 1 PaTime outputParameters->suggestedLatency: 0.135000 void *outputParameters->hostApiSpecificStreamInfo: 0x00000000 double sampleRate: 44100 unsigned long framesPerBuffer: 256 PaStreamFlags streamFlags: 0x0 PaStreamCallback *streamCallback: 0x00000000 void *userData: 0x00000000 Pa_GetSampleSize called: PaSampleFormat format: 8 Pa_GetSampleSize returned: int: 2 Pa_GetSampleSize called: PaSampleFormat format: 8 Pa_GetSampleSize returned: int: 2 Pa_GetSampleSize called: PaSampleFormat format: 1 Pa_GetSampleSize returned: int: 4 Pa_GetSampleSize called: PaSampleFormat format: 8 Pa_GetSampleSize returned: int: 2 Pa_GetSampleSize called: PaSampleFormat format: 8 Pa_GetSampleSize returned: int: 2 Pa_OpenStream returned: *(PaStream** stream): 0x03BEAD50 PaError: 0 ( Success ) everything seems correct except: PaStreamCallback *streamCallback: 0x00000000 void *userData: 0x00000000 You can find the full code at https://forum.dlang.org/thread/lkbswgpsgxynhfyzwfqz@forum.dlang.org This is either a bug in D, an issue with calling conventions, or how one passes the data. The original portaudio open stream function, so you can see that it simply prints it's arguments: PaError Pa_OpenStream( PaStream** stream, const PaStreamParameters *inputParameters, const PaStreamParameters *outputParameters, double sampleRate, unsigned long framesPerBuffer, PaStreamFlags streamFlags, PaStreamCallback *streamCallback, void *userData ) { PaError result; PaUtilHostApiRepresentation *hostApi = 0; PaDeviceIndex hostApiInputDevice = paNoDevice, hostApiOutputDevice = paNoDevice; PaStreamParameters hostApiInputParameters, hostApiOutputParameters; PaStreamParameters *hostApiInputParametersPtr, *hostApiOutputParametersPtr; #ifdef PA_LOG_API_CALLS PA_LOGAPI_ENTER_PARAMS( "Pa_OpenStream" ); PA_LOGAPI(("\tPaStream** stream: 0x%p\n", stream )); if( inputParameters == NULL ){ PA_LOGAPI(("\tPaStreamParameters *inputParameters: NULL\n" )); }else{ PA_LOGAPI(("\tPaStreamParameters *inputParameters: 0x%p\n", inputParameters )); PA_LOGAPI(("\tPaDeviceIndex inputParameters->device: %d\n", inputParameters->device )); PA_LOGAPI(("\tint inputParameters->channelCount: %d\n", inputParameters->channelCount )); PA_LOGAPI(("\tPaSampleFormat inputParameters->sampleFormat: %d\n", inputParameters->sampleFormat )); PA_LOGAPI(("\tPaTime inputParameters->suggestedLatency: %f\n", inputParameters->suggestedLatency )); PA_LOGAPI(("\tvoid *inputParameters->hostApiSpecificStreamInfo: 0x%p\n", inputParameters->hostApiSpecificStreamInfo )); } if( outputParameters == NULL ){ PA_LOGAPI(("\tPaStreamParameters *outputParameters: NULL\n" )); }else{ PA_LOGAPI(("\tPaStreamParameters *outputParameters: 0x%p\n", outputParameters )); PA_LOGAPI(("\tPaDeviceIndex outputParameters->device: %d\n", outputParameters->device )); PA_LOGAPI(("\tint outputParameters->channelCount: %d\n", outputParameters->channelCount )); PA_LOGAPI(("\tPaSampleFormat outputParameters->sampleFormat: %d\n", outputParameters->sampleFormat )); PA_LOGAPI(("\tPaTime outputParameters->suggestedLatency: %f\n", outputParameters->suggestedLatency )); PA_LOGAPI(("\tvoid *outputParameters->hostApiSpecificStreamInfo: 0x%p\n", outputParameters->hostApiSpecificStreamInfo )); } PA_LOGAPI(("\tdouble sampleRate: %g\n", sampleRate )); PA_LOGAPI(("\tunsigned long framesPerBuffer: %d\n", framesPerBuffer )); PA_LOGAPI(("\tPaStreamFlags streamFlags: 0x%x\n", streamFlags )); PA_LOGAPI(("\tPaStreamCallback *streamCallback: 0x%p\n", streamCallback )); PA_LOGAPI(("\tvoid *userData: 0x%p\n", userData )); #endif and this is how I define it in the code(which you can see if you follow the link): PaError function(PaStream** stream, const PaStreamParameters *inputParameters, const PaStreamParameters *outputParameters, double sampleRate, ulong framesPerBuffer, PaStreamFlags streamFlags, PaStreamCallback streamCallback, void *userData) Pa_OpenStream; I can play audio if I do a hard write, but obviously that is generally useless. This seems like it might be a bug in D in that the last parameters are invalid. user_data, which is passing a simple pointer is also 0, when it isn't. Even trying something like PaError function(PaStream** stream, const PaStreamParameters *inputParameters, const PaStreamParameters *outputParameters, double sampleRate, ulong framesPerBuffer, PaStreamFlags streamFlags, size_t streamCallback, size_t userData) Pa_OpenStream; and passing numbers still shows zero values! Any ideas? |
August 28, 2017 Re: C callbacks getting a value of 0! Bug in D? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Johnson Jones | Looking at the assembly shows something like this: 0041ea98 push 0x0 0041ea9a push 0x0 0041ea9c push 0x0 0041ea9e push dword 0x100 0041eaa3 mov ecx, [typeid(PaStreamParameters)+0xe36fc (0x80d4cc)] 0041eaa9 mov eax, [fs:0x2c] 0041eaaf mov edx, [eax+ecx*4] 0041eab2 push dword [edx+0x1c] 0041eab8 push dword [edx+0x18] 0041eabe push dword [ebp-0x54] 0041eac1 push dword [ebp-0x5c] 0041eac4 mov ebx, PA.stream (0x823f30) 0041eac9 push ebx 0041eaca call dword near [Pa_OpenStream (0x823f18)] I noticed that those 0's were the values being fed in to the function. I remember converting c_ulong's to ulong's and that they were probably uint's in D. Converting those fixed the problem and the callback is now called! I converted all the ulongs to uint's but there were a few longs and I don't know if they are c_longs or d_longs... Anyways, At least I'm on the right track. |
August 28, 2017 Re: C callbacks getting a value of 0! Bug in D? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Johnson Jones | On 8/27/17 10:17 PM, Johnson Jones wrote:
> Looking at the assembly shows something like this:
>
> 0041ea98 push 0x0
> 0041ea9a push 0x0
> 0041ea9c push 0x0
> 0041ea9e push dword 0x100
> 0041eaa3 mov ecx, [typeid(PaStreamParameters)+0xe36fc (0x80d4cc)]
> 0041eaa9 mov eax, [fs:0x2c]
> 0041eaaf mov edx, [eax+ecx*4]
> 0041eab2 push dword [edx+0x1c]
> 0041eab8 push dword [edx+0x18]
> 0041eabe push dword [ebp-0x54]
> 0041eac1 push dword [ebp-0x5c]
> 0041eac4 mov ebx, PA.stream (0x823f30)
> 0041eac9 push ebx
> 0041eaca call dword near [Pa_OpenStream (0x823f18)]
>
> I noticed that those 0's were the values being fed in to the function.
>
> I remember converting c_ulong's to ulong's and that they were probably uint's in D. Converting those fixed the problem and the callback is now called! I converted all the ulongs to uint's but there were a few longs and I don't know if they are c_longs or d_longs...
>
> Anyways, At least I'm on the right track.
>
For C/C++ interaction, always use c_... types if they are available. The idea is both that they will be correctly defined for the width, and also it will mangle correctly for C++ compilers (yes, long and int are mangled differently even when they are the same thing).
-Steve
|
August 28, 2017 Re: C callbacks getting a value of 0! Bug in D? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Monday, 28 August 2017 at 21:35:27 UTC, Steven Schveighoffer wrote:
> On 8/27/17 10:17 PM, Johnson Jones wrote:
>> [...]
>
> For C/C++ interaction, always use c_... types if they are available. The idea is both that they will be correctly defined for the width, and also it will mangle correctly for C++ compilers (yes, long and int are mangled differently even when they are the same thing).
>
> -Steve
and where are these c_ types defined? The reason I replaced them was precisely because D was not finding them.
|
August 28, 2017 Re: C callbacks getting a value of 0! Bug in D? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Johnson Jones | On Monday, 28 August 2017 at 22:21:18 UTC, Johnson Jones wrote:
> On Monday, 28 August 2017 at 21:35:27 UTC, Steven Schveighoffer wrote:
>> On 8/27/17 10:17 PM, Johnson Jones wrote:
>>> [...]
>>
>> For C/C++ interaction, always use c_... types if they are available. The idea is both that they will be correctly defined for the width, and also it will mangle correctly for C++ compilers (yes, long and int are mangled differently even when they are the same thing).
>>
>> -Steve
>
> and where are these c_ types defined? The reason I replaced them was precisely because D was not finding them.
core.stdc.config
, which unfortunately doesn't appear in the online documentation AFAICT (something that ought to be fixed).
A common workaround is to use pattern searching tools like grep if you know the phrase to look for:
$ grep -Er c_long /path/to/imports
, or in this case, since these things are usually done with aliases:
$ grep -Er 'alias\s+\w*\s+c_long' /path/to/imports
|
August 28, 2017 Re: C callbacks getting a value of 0! Bug in D? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Moritz Maxeiner | On Monday, 28 August 2017 at 22:41:56 UTC, Moritz Maxeiner wrote:
> On Monday, 28 August 2017 at 22:21:18 UTC, Johnson Jones wrote:
>> On Monday, 28 August 2017 at 21:35:27 UTC, Steven Schveighoffer wrote:
>>> [...]
>>
>> and where are these c_ types defined? The reason I replaced them was precisely because D was not finding them.
>
> core.stdc.config
>
> , which unfortunately doesn't appear in the online documentation AFAICT (something that ought to be fixed).
> A common workaround is to use pattern searching tools like grep if you know the phrase to look for:
> $ grep -Er c_long /path/to/imports
> , or in this case, since these things are usually done with aliases:
> $ grep -Er 'alias\s+\w*\s+c_long' /path/to/imports
Thanks. I copied over stuff from the bindings and from the original header and I guess I missed the import.
|
August 28, 2017 Re: C callbacks getting a value of 0! Bug in D? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Monday, 28 August 2017 at 21:35:27 UTC, Steven Schveighoffer wrote:
> On 8/27/17 10:17 PM, Johnson Jones wrote:
>> Looking at the assembly shows something like this:
>>
>> 0041ea98 push 0x0
>> 0041ea9a push 0x0
>> 0041ea9c push 0x0
>> 0041ea9e push dword 0x100
>> 0041eaa3 mov ecx, [typeid(PaStreamParameters)+0xe36fc (0x80d4cc)]
>> 0041eaa9 mov eax, [fs:0x2c]
>> 0041eaaf mov edx, [eax+ecx*4]
>> 0041eab2 push dword [edx+0x1c]
>> 0041eab8 push dword [edx+0x18]
>> 0041eabe push dword [ebp-0x54]
>> 0041eac1 push dword [ebp-0x5c]
>> 0041eac4 mov ebx, PA.stream (0x823f30)
>> 0041eac9 push ebx
>> 0041eaca call dword near [Pa_OpenStream (0x823f18)]
>>
>> I noticed that those 0's were the values being fed in to the function.
>>
>> I remember converting c_ulong's to ulong's and that they were probably uint's in D. Converting those fixed the problem and the callback is now called! I converted all the ulongs to uint's but there were a few longs and I don't know if they are c_longs or d_longs...
>>
>> Anyways, At least I'm on the right track.
>>
>
> For C/C++ interaction, always use c_... types if they are available. The idea is both that they will be correctly defined for the width, and also it will mangle correctly for C++ compilers (yes, long and int are mangled differently even when they are the same thing).
>
> -Steve
In portaudio, this doesn't seem to be the case. I changed all the longs to ints and ran my code in x64 and it worked fine.
It may just be that the stuff that uses long is not used in my code. In port audio I see it using unsigned long and so this should be 64-bits in x64. Surprised it worked. Maybe conversion is taking place or the high bits of the long are 0'ed and so there is not much difference.
Anyways, I guess I'll deal with any of those bugs when I run in to them, if they exist.
|
August 28, 2017 Re: C callbacks getting a value of 0! Bug in D? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Johnson Jones | On 8/28/17 7:47 PM, Johnson Jones wrote: > On Monday, 28 August 2017 at 21:35:27 UTC, Steven Schveighoffer wrote: >> On 8/27/17 10:17 PM, Johnson Jones wrote: >>> Looking at the assembly shows something like this: >>> >>> 0041ea98 push 0x0 >>> 0041ea9a push 0x0 >>> 0041ea9c push 0x0 >>> 0041ea9e push dword 0x100 >>> 0041eaa3 mov ecx, [typeid(PaStreamParameters)+0xe36fc (0x80d4cc)] >>> 0041eaa9 mov eax, [fs:0x2c] >>> 0041eaaf mov edx, [eax+ecx*4] >>> 0041eab2 push dword [edx+0x1c] >>> 0041eab8 push dword [edx+0x18] >>> 0041eabe push dword [ebp-0x54] >>> 0041eac1 push dword [ebp-0x5c] >>> 0041eac4 mov ebx, PA.stream (0x823f30) >>> 0041eac9 push ebx >>> 0041eaca call dword near [Pa_OpenStream (0x823f18)] >>> >>> I noticed that those 0's were the values being fed in to the function. >>> >>> I remember converting c_ulong's to ulong's and that they were probably uint's in D. Converting those fixed the problem and the callback is now called! I converted all the ulongs to uint's but there were a few longs and I don't know if they are c_longs or d_longs... >>> >>> Anyways, At least I'm on the right track. >>> >> >> For C/C++ interaction, always use c_... types if they are available. The idea is both that they will be correctly defined for the width, and also it will mangle correctly for C++ compilers (yes, long and int are mangled differently even when they are the same thing). >> > > In portaudio, this doesn't seem to be the case. I changed all the longs to ints and ran my code in x64 and it worked fine. > > It may just be that the stuff that uses long is not used in my code. In port audio I see it using unsigned long and so this should be 64-bits in x64. Surprised it worked. Maybe conversion is taking place or the high bits of the long are 0'ed and so there is not much difference. Then I think possibly the port audio bindings are not correct. It's also possible that long is not 64-bit even on the platform you are using. Finally, it's also possible that the D compiler is not generating the call correctly. When I test on my mac, c_long is 8-bytes. I'm not sure what it is in your case, try this code and see what happens: import core.stdc.config; pragma(msg, c_long.sizeof); // prints 8 on my box. And in c: #include <stdio.h> int main() { printf("%lu\n", sizeof(long)); // also prints 8 on my box return 0; } They should match. If they don't, that's a D bug (in either core.stdc.config or the compiler, I'm not sure which). If they do, then one of the other two possibilities is happening, and I would lean towards the bindings being incorrect. -Steve |
August 29, 2017 Re: C callbacks getting a value of 0! Bug in D? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Tuesday, 29 August 2017 at 00:42:45 UTC, Steven Schveighoffer wrote:
> On 8/28/17 7:47 PM, Johnson Jones wrote:
>> [...]
>
> Then I think possibly the port audio bindings are not correct. It's also possible that long is not 64-bit even on the platform you are using. Finally, it's also possible that the D compiler is not generating the call correctly.
>
> When I test on my mac, c_long is 8-bytes. I'm not sure what it is in your case, try this code and see what happens:
>
> import core.stdc.config;
>
> pragma(msg, c_long.sizeof); // prints 8 on my box.
>
> And in c:
>
> #include <stdio.h>
>
> int main()
> {
> printf("%lu\n", sizeof(long)); // also prints 8 on my box
> return 0;
> }
>
> They should match. If they don't, that's a D bug (in either core.stdc.config or the compiler, I'm not sure which). If they do, then one of the other two possibilities is happening, and I would lean towards the bindings being incorrect.
>
> -Steve
import core.stdc.config;
pragma(msg, c_long.sizeof);
prints 4UL
both on x64 and x86
and and C:
void foo()
{
int dummy;
switch (dummy) {
case sizeof(long) :
case sizeof(long) :
break;
}
}
produces 4 on both x86 and x64. So, I'm not sure how you are getting 8.
|
August 29, 2017 Re: C callbacks getting a value of 0! Bug in D? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Johnson Jones | On Tuesday, 29 August 2017 at 01:34:40 UTC, Johnson Jones wrote: > [...] > > > produces 4 on both x86 and x64. So, I'm not sure how you are getting 8. There are different 64bit data models [1] and it seems your platform uses LLP64, which uses 32bit longs. Am I correct in assuming you're on Windows (as they are the only major modern platform that I'm aware of that made this choice)? [1] https://en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models |
Copyright © 1999-2021 by the D Language Foundation