簡體   English   中英

使用RtlMoveMemory將VB6轉換為C#

[英]Converting VB6 using RtlMoveMemory to C#

我正在嘗試將現有的VB6應用程序轉換為C#。 該應用程序必須使用也是用VB6編寫的並且是ActiveX DLL的API。 我正在使用.NET Interop功能包裝此API,以便可以在C#中使用它。

問題是一些代碼獲取了字節數組,然后使用RtlMoveMemory()將其移至Struct中。 使用下面給出的C#代碼,我得到一個System.ArgumentException“值不在期望范圍內”異常。 我已經嘗試了此實現的各種排列以及編組,但是我對這方面的知識有些不了解。 我嘗試的所有操作均導致某種形式的未處理異常。

使用RtlMoveMemory()的解決方案會很好,但是使用編組的解決方案會更好。 希望這只是連接點的問題。

VB6代碼:

Public Declare Sub MoveIt Lib "kernel32.dll" Alias "RtlMoveMemory" (dest As Any, src As Any, ByVal bytes As Long)

Type IntEventStruct
    TTag As Double
    quality As Long
    Value As Single
End Type


Dim byteBuff(PACKETSIZE - 1) As Byte
Dim dEvent As IntEventStruct


Call DWApi.ReadEvent(code, DBIndex, TTStr, interval, byteBuff, errMsg)
Call MoveIt(dEvent, byteBuff(0), Len(dEvent))

C#代碼:

[DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
static extern void MoveIt(Object Destination, Object Source, long Length);

public struct ReadEventStruct
{
    public double TimeTag;
    public int Quality;
    public float Value;
}

byte[] byteBuff = new byte[BUFFER_SIZE];
ReadEventStruct dwRead = new ReadEventStruct();

this.dw.ReadEvent(pt.Plant, pt.Index, pt.Time, pt.Interval, ref byteBuff, ref errMsg);
MoveIt(dwRead, byteBuff, Marshal.SizeOf(dwRead));

ReadEvent()的相關API文檔(我無權訪問源代碼):

This routine retrieves process data for a specified point at a single time.
Calling convention:

Call DWPCAPI.ReadEvent(Plant As String, _
  iChannel As Long, _
  StartT As String, _
  Interval as Single, _
  Buffer() As Byte, _
  ErrMsg As String)

Buffer( ):  Byte buffer containing returned data.

您可以使用帶有固定指針的固定內存(請記住,C#使用托管內存,因此系統可以自由地在內存中移動對象)。

采用:

[DllImport("Kernel32.dll", EntryPoint = "RtlMoveMemory")]
private static unsafe extern void MoveMemory(void* dest, void* src, int size);

在您的方法中,類似:

fixed (byte* p = pointer )
{
    // RtlMoveMemory call
}

另一種方法是使用Marshal.PtrToStructure()

在對我的原始問題的評論中提供了最佳答案。 它建議使用BitConverter類而不是編組,但是由於注釋者沒有提供它作為答案,因此它是:

ReadEventStruct dwRead = new ReadEventStruct(); 
Array buffer = new byte[BUFFER_SIZE];

this.dw.ReadEvent(pt.Plant, pt.Index, pt.Time, pt.Interval, ref buffer, ref errMsg);

byte[] byteBuffer = (byte[])buffer;                         // Convert to byte[] so BitConverter class can be used

dwRead.TimeTag = BitConverter.ToDouble(byteBuffer, 0);      // First 8 bytes are TimeTag (double)
dwRead.Quality = BitConverter.ToInt32(byteBuffer, 8);       // Next 4 bytes are Quality (integer)
dwRead.Value   = BitConverter.ToSingle(byteBuffer, 12);     // Last 4 bytes are Value (float)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM