[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