In the callback function from my own library, I need to access the espeak_EVENT array. The problem is the UNION statement in the C source code:
typedef struct { espeak_EVENT_TYPE type; unsigned int unique_identifier; // message identifier (or 0 for key or character) int text_position; // the number of characters from the start of the text int length; // word length, in characters (for espeakEVENT_WORD) int audio_position; // the time in mS within the generated speech output data int sample; // sample id (internal use) void* user_data; // pointer supplied by the calling program union { int number; // used for WORD and SENTENCE events. For PHONEME events this is the phoneme mnemonic. const char *name; // used for MARK and PLAY events. UTF8 string } id; } espeak_EVENT;
I have
[StructLayout(LayoutKind.Explicit)] public struct espeak_EVENT { [System.Runtime.InteropServices.FieldOffset(0)] public espeak_EVENT_TYPE type; [System.Runtime.InteropServices.FieldOffset(4)] public uint unique_identifier;
And then
public static Int32 SynthCallback(IntPtr wav, Int32 numsamples, IntPtr eventsParameter) { if (wav == IntPtr.Zero) return 0; int j=0; while(true) { System.IntPtr ptr = new IntPtr( ( eventsParameter.ToInt64() + (j * System.Runtime.InteropServices.Marshal.SizeOf(typeof(cEspeak.espeak_EVENT)) ) ) ); if(ptr == IntPtr.Zero) Console.WriteLine("NULL"); cEspeak.espeak_EVENT events = (cEspeak.espeak_EVENT) System.Runtime.InteropServices.Marshal.PtrToStructure(ptr, typeof(cEspeak.espeak_EVENT)); if(events.type == cEspeak.espeak_EVENT_TYPE.espeakEVENT_SAMPLERATE) { Console.WriteLine("Heureka"); } break;
But he always fails on
cEspeak.espeak_EVENT events = (cEspeak.espeak_EVENT) System.Runtime.InteropServices.Marshal.PtrToStructure(ptr, typeof(cEspeak.espeak_EVENT));
However, when I delete
[System.Runtime.InteropServices.FieldOffset(32)][System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPStr)] public string name;
From espeak_event, then it works.
How can I do this work without deleting a row in a join? I need to access it in a callback function.
Edit: And by the way, what happens to field offsets if I allow it to run on x64 and the size is "public IntPtr user_data;" varies from 32 to 64 bits?
Hmm, thinking about it, is polefoss 32 true? It seems I mixed the size of the pointer while thinking about x64. Perhaps this will be another mistake.
Hm, combining with int and char *, I think they never compiled it for x64. Since sizof (int) is 32 bits on x64 Linux system.