[Mono-osx] P/invoking the OS X speech API?
Nolan Darilek
nolan at thewordnerd.info
Tue Feb 21 23:05:46 EST 2006
Hello. I recently begun attempting to wrap the OS X speech API in a
DLL, but never having done p/invoke code before, I'm encountering
some issues (namely, segfaults.)
First, has anyone done this before? If so then do let me know, as I'd
definitely like to see what you've accomplished. :) But, if not,
here's what I have so far.
Here are the functions/structures I'm trying to wrap, from
SpeechSynthesis.h:
struct SpeechChannelRecord {
long data[1];
};
typedef struct SpeechChannelRecord SpeechChannelRecord;
typedef SpeechChannelRecord * SpeechChannel;
...
/*
* NewSpeechChannel()
*
* Availability:
* Mac OS X: in version 10.0 and later in
ApplicationServices.framework
* CarbonLib: in CarbonLib 1.0 and later
* Non-Carbon CFM: in SpeechLib 1.0 and later
*/
extern OSErr
NewSpeechChannel(
VoiceSpec * voice, /* can be NULL */
SpeechChannel * chan)
AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER;
...
/*
* SpeakText()
*
* Availability:
* Mac OS X: in version 10.0 and later in
ApplicationServices.framework
* CarbonLib: in CarbonLib 1.0 and later
* Non-Carbon CFM: in SpeechLib 1.0 and later
*/
extern OSErr
SpeakText(
SpeechChannel chan,
const void * textBuf,
unsigned long textBytes)
AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER;
And my code thus far:
using System;
using System.Runtime.InteropServices;
namespace Meridian.Tts.Osx {
[StructLayout(LayoutKind.Sequential)]
struct SpeechChannel {
[MarshalAs(UnmanagedType.ByValArray, SizeConst=1)]
long[] data;
}
public class Channel {
private SpeechChannel _id;
protected const string _applicationServicesPath = "/System/Library/
Frameworks/ApplicationServices.framework/Versions/Current/
ApplicationServices";
[DllImport(_applicationServicesPath)]
private static extern short NewSpeechChannel(IntPtr voice, ref
SpeechChannel channel);
[DllImport(_applicationServicesPath)]
private static extern short SpeakText(SpeechChannel channel, String
text, long length);
public Channel() {
short rc = NewSpeechChannel((IntPtr)null, ref _id);
Console.WriteLine(rc);
Speak("Hello, world.");
}
public bool Speak(String text) {
short rc = SpeakText(_id, text, (long)text.Length);
return (rc == 0);
}
}
}
This code segfaults in Channel.Speak(). Questions:
I'll never need to access the data member of SpeechChannel. Should I
do away with using struct for that and use IntPtr instead? Can I use
IntPtr if I'm using both the struct and its address? (I.e.
NewSpeechChannel takes a reference while SpeakText does not.)
How do I handle the fact that I want Channel.Speak() to accept a
string, but SpeakText() expects a void pointer? Is that why this is
segfaulting?
Is there anything else I'm missing?
Thanks.
More information about the Mono-osx
mailing list