Page 1 of 1

DllCall returning const char **

Posted: 11 Sep 2017, 06:24
by potscrubber
Hello AHK guru's

I have a pretty good background with ahk macro's and app manipulations. I have delved into DllCall's for some basic tasks and got things happening. AHK is great!
I have hit a wall with this though. I am querying the well known PortAudio audio I/O library. I can initialize it, and get basic values returned like integers and stuff. However I am trying to get a return value of const char ** type.

I think I get that it's a pointer to a pointer of string. But I cannot for the life of me get a string from it.

I should note that this script will not run successfully on your system unless you have portaudio_x64.dll, and a soundcard with an ASIO driver.

However, DllCall experts may be able to point me in the right direction after parsing the code. I should note that my AHK is installed for x64 Unicode. My ASIO soundcard has x64 drivers. I'm on Win7 Pro x64.

This is the documetation here for the function I am trying to access:

Code: Select all

PaError PaAsio_GetOutputChannelName 	( 	PaDeviceIndex  	device,
											int  	channelIndex,
											const char **  	channelName 
										)
Retrieve a pointer to a string containing the name of the specified input channel. The string is valid until Pa_Terminate is called.
The string will be no longer than 32 characters including the null terminator. 										
I can get a numeric value returned as a pointer, but no way can I get a string. For PaAsio_GetOutputChannelName, if I substitute "Ptr" with any type of Str I get exception code c0000005 - access violation. Additionaly, I can't find the way to get the string from the pointer (reflected in the code below).

Any help would be hugely appreciated! Thanks....

Code: Select all

SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

paNoError = 0
hModule := DllCall("LoadLibrary", "Str", "portaudio_x64.dll", "Ptr")  ; load dll
err := DllCall("portaudio_x64\Pa_Initialize")
if( err != paNoError )
{
	errtxt := DllCall("portaudio_x64\Pa_GetErrorText", "Int", err, "AStr")   ;Astr for const char*
	MsgBox, Pa_Initialize: %errtxt%
}

Result := DllCall("portaudio_x64\Pa_GetDeviceCount", "Int")
MsgBox, Pa_GetDeviceCount: %Result%

; all works ok up until here - below is the problem

device = 0
channel = 0
VarSetCapacity(err,  64 * (A_IsUnicode ? 2 : 1))
err := DllCall("portaudio_x64\PaAsio_GetOutputChannelName", "Int", device, "Int", channel, "Ptr")
addr := NumGet(err, "Ptr")	; just an attempt
str := StrGet(addr, 64, "AStr")   ; just an attempt

MsgBox, PaAsio_GetOutputChannelName:`n err: %err%`n addr: %addr%`n str: %str%
; err returns 4294957300 
; addr returns 14636943605366836
; str returns nothing

; just tidying up from here, all ok

err := DllCall("portaudio_x64\Pa_Terminate")
if( err != paNoError )
{
	errtxt := DllCall("portaudio_x64\Pa_GetErrorText", "Int", err, "AStr")   ;Astr for const char*
	MsgBox, Pa_Terminate: %errtxt%
}
DllCall("FreeLibrary", "Ptr", hModule)  ; unload dll
return

Re: DllCall returning const char **

Posted: 11 Sep 2017, 07:14
by Helgef
Hello. The return seems to be an int. You need to use "ptr*", channelName. Then strget(channelName, "cp0"). Disclaimer, I'm on the phone so typing and reading is awkward. I have an asio card so I can test later if this didnt help. Cheers

Re: DllCall returning const char **

Posted: 11 Sep 2017, 07:34
by potscrubber
Hi Helgef

Thanks for your reply, much appreciated. When I try ptr* I get the access violation exception that I mentioned before. I've tried dozens of combinations in the past, but as you can tell, I'm stabbing in the dark as I don't fully understand data types and memory pointers.

If you did want to try it, you can get the portaudio dll here - though they have different file names than in my code - but work the same.

Thanks again

Re: DllCall returning const char **

Posted: 11 Sep 2017, 12:48
by Helgef
Hello. Unfortunately I do not have any luck with Pa_GetDeviceCount, I get back -10000, which indicates an error.
This is what I had in mind though, did you test it like this?

Code: Select all

device = 0
err := DllCall("portaudio_x64\PaAsio_GetOutputChannelName", "Int", device, "int", channelIndex, "Ptr*", channelName, "Int")
str := StrGet(channelName, "cp0")
cheers.

Edit: I stumbled upon this old thread while searching for something else, I've corrected a few errors in my posts.

Re: DllCall returning const char **

Posted: 11 Sep 2017, 16:34
by potscrubber
Hello Helgef .

I didn't quite write the way you did first time, but using your code above I get err returning -9996 which means Invalid device. That's the other common result I've had apart from exceptions.

But thanks for the suggestion. I will keep tinkering, you may have set me on the right path.

By the way, -10000 means PortAudio not initialized.

cheers.