I have a native library and what I'm trying to do is to write a .NET Core wrapper to this native library.
On the native side i have an event called OnSpeechEnded :
virtual void OnSpeechEnded(SpeechEndInfo seInfo) = 0;
and native struct SpeechEndInfo has the following structure:
struct SpeechEndInfo
{
std::vector<AudioData> UntouchedData;
std::vector<AudioData> AudioAfterPostSpeechUntilSilenceTrigger;
};
Corresponding .NET Standard Class:
public struct SpeechEndedInfo
{
public SpeechEndedInfo(short[] untouchedData, short[] audioAfterPostSpeechUntilSilenceTrigger)
{
UntouchedData = new short[untouchedData.Length];
untouchedData.CopyTo(UntouchedData, 0);
AudioAfterPostSpeechUntilSilenceTrigger = new short[audioAfterPostSpeechUntilSilenceTrigger.Length];
audioAfterPostSpeechUntilSilenceTrigger.CopyTo(AudioAfterPostSpeechUntilSilenceTrigger, 0);
}
public short[] UntouchedData { get; set; }
public short[] AudioAfterPostSpeechUntilSilenceTrigger { get; set; }
};
On .NET Standard side, the following delegate is defined:
delegate void OnSpeechEndedInter(
[In, MarshalAs(UnmanagedType.LPArray)] short[] untouched,
int untouchedSize,
[In, MarshalAs(UnmanagedType.LPArray)] short[] audioAfterPostSpeechUntilSilenceTrigger,
int audioAfterPostSpeechUntilSilenceTriggerSize);
Declaring pinvoke:
[DllImport("VadLite.Pinvokable.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern void RegisterToSpeechEndedEvent(IntPtr parameters, [MarshalAs(UnmanagedType.FunctionPtr)]OnSpeechEndedInter onSpeechEndedInter);
Declaring _onSpeechEndedInter:
private OnSpeechEndedInter _onSpeechEndedInter;
Assigning a method to the event:
_onSpeechEndedInter = invokedMethod;
...
void invokedMethod(short[] untouchedData,
int untouchedSize,
short[] audioAfterPostSpeechUntilSilenceTrigger,
int audioAfterPostSpeechUntilSilenceTriggerSize)
{
OnSpeechEnded?.Invoke(new SpeechEndedInfo(untouchedData, audioAfterPostSpeechUntilSilenceTrigger));
}
Finally, the code where native arrays are sent:
RegisterToSpeechEndedEvent(
void * possiblyOperations,
void __stdcall onSpeechEndedListener(const int16_t* pUntouchedData, int pUntouchedDataSize, const int16_t *vAudioAfterPostSpeechUntilSilenceTrigger, int vAudioAfterPostSpeechUntilSilenceTriggerSize))
{
auto op = (OperationParameters *)possiblyOperations;
op->OnSpeechEnded([onSpeechEndedListener](SpeechEndInfo ssInfo) {
std::vector<int16_t> untouchedData;
std::vector<int16_t> audioAfterPostSpeechUntilSilenceTrigger;
for (auto & audioData : ssInfo.UntouchedData)
{
untouchedData.insert(untouchedData.end(), audioData.Samples, audioData.Samples + audioData.SampleCount);
}
for (auto & audioData : ssInfo.AudioAfterPostSpeechUntilSilenceTrigger)
{
audioAfterPostSpeechUntilSilenceTrigger.insert(audioAfterPostSpeechUntilSilenceTrigger.end(), audioData.Samples, audioData.Samples + audioData.SampleCount);
}
onSpeechEndedListener(untouchedData.empty() ? nullptr : untouchedData.data(),
(int)untouchedData.size(),
audioAfterPostSpeechUntilSilenceTrigger.empty() ? nullptr : audioAfterPostSpeechUntilSilenceTrigger.data(),
(int)audioAfterPostSpeechUntilSilenceTrigger.size());
});
After running the test program and getting meaningful array sizes on the native side, C# arrays UntouchedData and AudioAfterPostSpeechUntilSilenceTrigger always seem to have size 1.
Probably there is a detail I have missed. I can provide further detail if it is required. Thanks.