Re: C callbacks getting a value of 0! Bug in D?

2017-08-29 Thread Steven Schveighoffer via Digitalmars-d-learn

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?

2017-08-28 Thread Moritz Maxeiner via Digitalmars-d-learn

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?

2017-08-28 Thread Johnson Jones via Digitalmars-d-learn

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?

2017-08-28 Thread Mike Parker via Digitalmars-d-learn

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?

2017-08-28 Thread Moritz Maxeiner via Digitalmars-d-learn

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?

2017-08-28 Thread Johnson Jones via Digitalmars-d-learn
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?

2017-08-28 Thread Steven Schveighoffer via Digitalmars-d-learn

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?

2017-08-28 Thread Johnson Jones via Digitalmars-d-learn
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?

2017-08-28 Thread Johnson Jones via Digitalmars-d-learn

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?

2017-08-28 Thread Moritz Maxeiner via Digitalmars-d-learn

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?

2017-08-28 Thread Johnson Jones via Digitalmars-d-learn
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?

2017-08-28 Thread Steven Schveighoffer via Digitalmars-d-learn

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?

2017-08-27 Thread Johnson Jones via Digitalmars-d-learn

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?

2017-08-27 Thread Johnson Jones via Digitalmars-d-learn
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 ));