我一直在使用一个接口(interface)来从传感器读取测量数据,并使用以C++编写的库来分析该数据。

该功能大致如下:

  • 在C++库
  • 上设置测量参数
  • 从传感器获取数据(总共进行了1200次测量)
  • 将数据写入C++库
  • 处理C++库
  • 中的所有1200个测量值
  • 从C++库
  • 中读取结果

    从C#代码调用此C++库以前已解决以下问题:Calling unmanaged C++ library (dll) from C# creates an access violation error (0xc0000005).

    现在看来,C++库要么
  • 无法正确获取数据
  • 无法保存数据
  • 无法将结果正确返回到我的C#代码。

  • 不好的是,我无法调试此C++库。

    我的代码有什么问题?

    1)设置测量参数
    namespace PdWaveApi
    {
    [StructLayout(LayoutKind.Sequential)]
    public struct PDDataInfo
    
    {
       public int   nPings;
       public int   nDataRate;
       public int   nSamples;
       public float fFrequency;
       public float fBeamAngle;
       public int   nInstrument;
       public int   nCoordSystem;
       [MarshalAs(UnmanagedType.ByValArray, SizeConst = 9)]
       public short[] hBeamToXYZ;
       public short hWaveT1;
    
        // Constructor
       public static PDDataInfo Create()
       {
           PDDataInfo DataStruct = new PDDataInfo();
           DataStruct.hBeamToXYZ = new short[9];
           return DataStruct;
       }
       }
    }
    
    public class PdWaveBaseLWrapper
    {
       [DllImport("PdWaveBase.dll", EntryPoint = "PDSetInstrumentConfig")]
       public static extern int PDSetInstrumentConfig(ref PDDataInfo pDataInfo);
    }
    
    public void SetInstrumentConfiguration()
    {
        PdWaveApi.PDDataInfo InstrumentConfiguration = new PdWaveApi.PDDataInfo();
        .................
        Initializing the InstrumentConfiguration structure
        ...............
        PdWaveBaseLWrapper.PDSetInstrumentConfig(ref InstrumentConfiguration);
    }
    

    3)从传感器读取数据并将数据写入C++库
    namespace PdWaveApi
    {
        [StructLayout(LayoutKind.Sequential)]
        public struct PDWaveSample
        {
            [MarshalAs(UnmanagedType.I1)]
            public bool Valid;
            public float fPressure;
            public float fDistance;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.PD_MAX_WAVEBEAMS)]
            public float[] fVel;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.PD_MAX_WAVEBEAMS)]
            public ushort[] nAmp;
    
            // Constructor
    
            public static PDWaveSample Create()
            {
                PDWaveSample DataStruct = new PDWaveSample();
                DataStruct.fVel = new float[Constants.PD_MAX_WAVEBEAMS];
                DataStruct.nAmp = new ushort[Constants.PD_MAX_WAVEBEAMS];
                return DataStruct;
            }
        }
    }
    
    public class PdWaveBaseLWrapper
    {
        [DllImport("PdWaveBase.dll", EntryPoint = "PDSetWaveSample")]
        public static extern int PDSetWaveSample(ref PDWaveSample pWaveSample);
    }
    
    namespace SensorInterface
    {
        public partial class frmSensorInterface : Form
        {
            public PdWaveApi.PDWaveSample WaveSampleData = PdWaveApi.PDWaveSample.Create();
    
            private void OnNewData(object sender, OnNewDataEvent e)
            {
                ReadWaveSample(ref WaveSampleData);
                SetWaveSample(ref WaveSampleData);
            }
    
            public void ReadWaveSample(ref PdWaveApi.PDWaveSample WaveSampleData)
            {
                DateTime MeasurementTimeStamp;
                float[] dVel = new float[4];
                float dTemperature = new float();
                float dPitch = new float();
                float dRoll = new float();
                float dHeading = new float();
                float dPressure = new float();
                short[] sAmp = new short[4];
    
                //  Read some of the latest data from the control
                GetVelocity(ref dVel[0], ref dVel[1], ref dVel[2], ref dVel[3]);
                GetAmplitude(ref sAmp[0], ref sAmp[1], ref sAmp[2], ref sAmp[2]);
    
                ..............
                // Set other data to the structure
    
            }
    
            public void SetWaveSample(ref PdWaveApi.PDWaveSample WaveSampleData)
            {
                PdWaveBaseLWrapper.PDSetWaveSample(ref WaveSampleData);
            }
        }
    }
    

    4)在C++库中处理所有1200次测量
    [StructLayout(LayoutKind.Sequential)]
    public struct PDWaveBurst
    {
        [MarshalAs(UnmanagedType.ByValArray , SizeConst = Constants.PD_MAX_WAVEMEAS_AST)]
        public float[] fST;
        public float fWinFloor;
        public float fWinCeil;
        [MarshalAs(UnmanagedType.I1)]
        public bool bUseWindow;
        [MarshalAs(UnmanagedType.I1)]
        public bool bSTOk;
        [MarshalAs(UnmanagedType.I1)]
        public bool bGetRawAST;
        [MarshalAs(UnmanagedType.I1)]
        public bool bValidBurst;
    
        public static PDWaveBurst Create()
        {
            PDWaveBurst DataStruct = new PDWaveBurst();
            DataStruct.fST = new float[Constants.PD_MAX_WAVEMEAS_AST];
            return DataStruct;
        }
    }
    
    [DllImport("PdWaveBase.dll", EntryPoint = "PDPreProcess")]
    public static extern int PDPreProcess(int nSample, ref PDWaveBurst pWaveBurst);
    
    [DllImport("PdWaveBase.dll", EntryPoint = "PDProcessReturnInt")]
    public static extern int PDProcessReturnInt();
    
    public void PreprocessBurstData(int nSamples)
    {
        PdWaveApi.PDWaveBurst WaveBurstData = PdWaveApi.PDWaveBurst.Create();
    
        WaveBurstData.fST = new float[4096];
        WaveBurstData.fWinFloor = (float)1.25;
        WaveBurstData.fWinCeil = 2;
        WaveBurstData.bUseWindow = false;
        WaveBurstData.bSTOk = false;
        WaveBurstData.bGetRawAST = false;
        WaveBurstData.bValidBurst = false;
    
        PdWaveBaseLWrapper.PDPreProcess(nSamples, ref WaveBurstData);
    }
    
    public void ProcessData()
    {
        int ProcessError = PdWaveBaseLWrapper.PDProcessReturnInt();
    }
    

    5)从C++库读取结果
    [StructLayout(LayoutKind.Sequential)]
    public struct PDWavePar {
       public float fTm02;
       public float fTp;
       public float fDirTp;
       public float fSprTp;
       public float fMainDir;
       public float fUI;
       public float fHm0;
       public float fH3;
       public float fT3;
       public float fH10;
       public float fT10;
       public float fHmax;
       public float fTmax;
       public float fTz;
       public float fMeanPres;
       public int   nNumNoDet;
       public int   nNumBadDet;
       public int   nErrCode;
       public int   nSpectrum;
       public float fMeanAST;
    }
    
    
    [DllImport("PdWaveBase.dll", EntryPoint = "PDGetWavePar")]
    public static extern int PDGetWavePar(ref PDWavePar pwWavePar);
    
    public void GetOutput()
    {
        PdWaveApi.PDWavePar WaveParameters = new PdWaveApi.PDWavePar();
        PdWaveBaseLWrapper.PDGetWavePar(ref WaveParameters);
    }
    

    因此,作为结论:

    我应该在代码中更改什么
    -将数据正确传递到非托管dll
    -使dll保留并处理其内部结构中的数据
    -从非托管代码正确读取结果到我的C#程序?

    (很抱歉,我的提问时间太长了。)

    最佳答案

    我的问题的最终解决方案是将对齐方式更改为1个字节,如下所示:

    C#结构定义:
    从:

        [StructLayout(LayoutKind.Sequential)]
    


        [StructLayout(LayoutKind.Sequential, Pack=1)]
    

    至少在这里对此进行了讨论:
    Calling C++ metro dll from c# metro app and returning filled structures

    10-04 21:27
    查看更多