Re: C callbacks getting a value of 0! Bug in D?
On 8/28/17 9:34 PM, Johnson Jones wrote: produces 4 on both x86 and x64. So, I'm not sure how you are getting 8. Yes, this is exactly why you should use c_long and c_ulong, because just using int makes it not portable to other systems. -Steve
Re: C callbacks getting a value of 0! Bug in D?
On Tuesday, 29 August 2017 at 02:47:34 UTC, Johnson Jones wrote: [...] Seems only long and ulong are issues. With respect to the currently major platforms you can reasonable expect software to run on, yes. Just don't try to use D on something with e.g. 32 bit C shorts unless you bind to it via c_short.
Re: C callbacks getting a value of 0! Bug in D?
On Tuesday, 29 August 2017 at 01:56:43 UTC, Moritz Maxeiner wrote: 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 Yes. I found this, which gives a map for all the types: https://dlang.org/spec/interfaceToC.html Seems only long and ulong are issues.
Re: C callbacks getting a value of 0! Bug in D?
On Tuesday, 29 August 2017 at 01:34:40 UTC, Johnson Jones wrote: 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. It's because you're on Windows. There, long/ulong are 4 bytes in both 32- and 64-bit. On Linux/Mac/*BSD, they're 4 in 32-bit and 8 in 64-bit. This is why we have c_long and c_ulong, to hide those differences.
Re: C callbacks getting a value of 0! Bug in D?
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
Re: C callbacks getting a value of 0! Bug in D?
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 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.
Re: C callbacks getting a value of 0! Bug in D?
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 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
Re: C callbacks getting a value of 0! Bug in D?
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.
Re: C callbacks getting a value of 0! Bug in D?
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.
Re: C callbacks getting a value of 0! Bug in D?
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
Re: C callbacks getting a value of 0! Bug in D?
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.
Re: C callbacks getting a value of 0! Bug in D?
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
Re: C callbacks getting a value of 0! Bug in D?
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.
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(, 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 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: 0x double sampleRate: 44100 unsigned long framesPerBuffer: 256 PaStreamFlags streamFlags: 0x0 PaStreamCallback *streamCallback: 0x void *userData: 0x 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: 0x void *userData: 0x You can find the full code at https://forum.dlang.org/thread/lkbswgpsgxynhfyzw...@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 ));