gpt4 book ai didi

c# - 通过 Net Core 将 C++ 数组传递到 C# 层

转载 作者:太空宇宙 更新时间:2023-11-04 12:33:42 25 4
gpt4 key购买 nike

我有一个 native 库,我想做的是为这个 native 库编写一个 .NET Core 包装器。

在 native 方面,我有一个名为 OnSpeechEnded 的事件:

virtual void OnSpeechEnded(SpeechEndInfo seInfo) = 0;

和原生结构 SpeechEndInfo 具有以下结构:

struct SpeechEndInfo
{
std::vector<AudioData> UntouchedData;
std::vector<AudioData> AudioAfterPostSpeechUntilSilenceTrigger;
};

对应的 .NET 标准类:

 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; }
};

在 .NET Standard 端,定义了以下委托(delegate):

delegate void OnSpeechEndedInter(
[In, MarshalAs(UnmanagedType.LPArray)] short[] untouched,
int untouchedSize,
[In, MarshalAs(UnmanagedType.LPArray)] short[] audioAfterPostSpeechUntilSilenceTrigger,
int audioAfterPostSpeechUntilSilenceTriggerSize);

声明pinvoke:

[DllImport("VadLite.Pinvokable.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern void RegisterToSpeechEndedEvent(IntPtr parameters, [MarshalAs(UnmanagedType.FunctionPtr)]OnSpeechEndedInter onSpeechEndedInter);

声明 _onSpeechEndedInter:

 private OnSpeechEndedInter _onSpeechEndedInter;

为事件分配一个方法:

 _onSpeechEndedInter = invokedMethod;

...

void invokedMethod(short[] untouchedData, 
int untouchedSize,
short[] audioAfterPostSpeechUntilSilenceTrigger,
int audioAfterPostSpeechUntilSilenceTriggerSize)
{
OnSpeechEnded?.Invoke(new SpeechEndedInfo(untouchedData, audioAfterPostSpeechUntilSilenceTrigger));
}

最后是发送原生数组的代码:

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());

});

在运行测试程序并在 native 端获得有意义的数组大小后,C# 数组 UntouchedData 和 AudioAfterPostSpeechUntilSilenceTrigger 的大小似乎始终为 1。

可能有一个细节我错过了。如果需要,我可以提供更多详细信息。谢谢。

最佳答案

太棒了!我终于找到问题所在了。在委托(delegate)声明中,我只需要引入参数 SizeParamIndex :

delegate void OnSpeechEndedInter(
[In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] short[] untouched,
int untouchedSize,
[In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] short[] audioAfterPostSpeechUntilSilenceTrigger,
int audioAfterPostSpeechUntilSilenceTriggerSize);

因为编码(marshal)拆收器无法确定非托管数组的大小,考虑到方法的签名和基于零的索引,我们必须将其作为单独的参数传入。

关于c# - 通过 Net Core 将 C++ 数组传递到 C# 层,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57395942/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com