gpt4 book ai didi

c# - 从 C# : How to properly pass data between managed and unmanaged code 调用非托管 C++ 库 (dll)

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:30:58 25 4
gpt4 key购买 nike

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

函数大致如下:

  1. 在 C++ 库上设置测量参数
  2. 从传感器获取数据(总共 1200 次测量)
  3. 将数据写入C++库
  4. 在 C++ 库中处理所有 1200 个测量值
  5. 从 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

关于c# - 从 C# : How to properly pass data between managed and unmanaged code 调用非托管 C++ 库 (dll),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12175077/

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