![](/img/trans.png)
[英]Calling a C++ dll (unmanaged code) from a C# windows service (written in managed code)
[英]Calling unmanaged C++ library (dll) from C# : How to properly pass data between managed and unmanaged code
我一直在使用從傳感器讀取測量數據並使用C ++編寫的庫來分析該數據的接口。
該功能大致如下:
從C#代碼調用此C ++庫以前已解決以下問題:從C# 調用非托管C ++庫(dll)會產生訪問沖突錯誤(0xc0000005)。
現在看來,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)]
至少在這里已對此進行了討論: 從c#Metro應用程序調用C ++ Metro dll並返回填充的結構
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.