简体   繁体   English

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

[英]Passing a C++ Array to C# Layer through Net Core

I have a native library and what I'm trying to do is to write a .NET Core wrapper to this native library. 我有一个本机库,我想做的是向该本机库编写一个.NET Core包装器。

On the native side i have an event called OnSpeechEnded : 在本机方面,我有一个名为OnSpeechEnded的事件:

virtual void OnSpeechEnded(SpeechEndInfo seInfo) = 0;

and native struct SpeechEndInfo has the following structure: 原生结构SpeechEndInfo具有以下结构:

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

Corresponding .NET Standard Class: 相应的.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; }
    };

On .NET Standard side, the following delegate is defined: 在.NET Standard方面,定义了以下委托:

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

Declaring pinvoke: 宣告pinvoke:

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

Declaring _onSpeechEndedInter: 声明_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. 运行测试程序并在本机端获取有意义的数组大小之后,C#数组UntouchedData和AudioAfterPostSpeechUntilSilenceTrigger似乎总是具有大小1。

Probably there is a detail I have missed. 可能有一个我错过的细节。 I can provide further detail if it is required. 如果需要,我可以提供更多详细信息。 Thanks. 谢谢。

Great!, Finally I have found out the problem. 太好了,终于找到了问题所在。 In the delegate declaration, I just had to introduce parameter SizeParamIndex : 在委托声明中,我只需要引入参数SizeParamIndex

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

Because the marshaler cannot determine the size of an unmanaged array, we have to pass it in as a separate parameter considering the signature of the method and zero based indexing. 由于封送拆封器无法确定非托管数组的大小,因此必须考虑方法的签名和从零开始的索引,将其作为单独的参数传递。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM