Estoy usando Delphi 2009 no se que tiene un gran efecto en lo que estoy haciendo. Creo que se podría ejecutar en el mismo si yo todavía estaba en 2007.

Tengo un scsi de la llamada que envía los datos a un puntero (de manera equivocada de ver las cosas, pero tengo problemas para explicar que).

Originalmente solía Mover para llenar un Estática de la Matriz de Bytes con los datos que volvió, pero me gustaría cambiar a un Matriz Dinámica a que la longitud de la que se conoce en el momento de la llamada. He intentado varias cosas con variados resultados a obtener los datos, pero tienen loco acceso violaciones a los demás de no tener errores, pero conseguir datos no válidos.

La adición de setlength a la matriz y, a continuación, utilizando mover, causa primera para tener una matriz vacía de longitud y la segunda a no ser capaz de acceder a los datos a través de como OutputData[0] como yo lo hice cuando era estático, en el depurador después de la mudanza todo lo que se muestra como innaccesable valor o lo que sea.

A continuación es algo que he intentado después de leer un artículo que hizo el oposit tomó una matriz dinámica y dio un puntero a esa dirección. Se menciona a cometer errores como la orfandad de datos.

var
  Output: Pointer;
  OutputData: Array of byte;
  I: Integer;
begin
GetMem(Output, OutputLength.Value);
if SendPSPQuery(Char(DriveLetter[1]), cbxQuery.Items.IndexOf(cbxQuery.Text), Output, OutputLength.Value) = 0 then
  begin
    OutputData := @Output;
    for I := 0 to OutputLength.Value - 1 do
    begin
      edtString.Text := edtString.Text + Char(OutputData[I]);
    end;

Hay varios otherstuff que th eoutput de datos que se utiliza para que se deposita en cadena y hexagonal y las cosas.

De todos modos, ¿cómo puedo Tomar un Puntero poner los datos en una matriz dinámica y, a continuación, que coge los datos de la forma de dirección de una matriz.

Gracias.

InformationsquelleAutor | 2009-03-10

4 Comentarios

  1. 10

    El uso de una matriz dinámica con el Mover procedimiento, usted necesita para pasar el primer elemento de la matriz. Por ejemplo:

    var
      Source: Pointer;
      SourceSize: Integer;
      Destination: array of Byte;
    
    SetLength(Destination, SourceSize);
    Move(Source^, Destination[0], SourceSize);

    Observe también que el segundo parámetro elimina las referencias el puntero. Eso es porque Move toma la valor que está copiando, no un puntero al valor. Va a copiar las cosas que el puntero apunta a eso es a lo que usted necesite para pasar a Move.

    Por cierto, de que la sintaxis es la misma funciona si Destination es una matriz estática, demasiado. Y tienes razón que no es específica de Delphi 2009. Es cierto que todo el camino de regreso a Delphi 4, que es cuando los vectores dinámicos fueron introducidas. Y Move ha tenido la misma extraña tipo de parámetro sintaxis para siempre.


    No asignar su propia memoria con GetMem y, a continuación, escriba fundido para hacer que el compilador creo que lo que tienes es una matriz dinámica. No. Matrices dinámicas tienen recuentos de referencia y campos de longitud que un ordinario byte del búfer no tiene, y ya que usted no está en control de todo el código que genera el compilador para acceder a la supuesta matriz dinámica, existe el peligro de que el programa intenta acceder a los datos de la estructura de la inexistente datos.

    Podría hacer que la PSP función de almacenar sus datos directamente en una matriz dinámica. Aquí un poco de código para hacerlo:

    var
      Output: array of Byte;
    
    SetLength(Output, OutputLength.Value);
    if SendPSPQuery(Char(DriveLetter[1]),
                    cbxQuery.Items.IndexOf(cbxQuery.Text),
                    @Output[0],
                    OutputLength.Value) = 0
    then

    No hay necesidad de liberar la memoria después; el compilador inserta el código para cancelar la asignación de la matriz dinámica cuando Output sale del ámbito y no hay otras referencias a la matriz. Este código tiene una matriz dinámica y se lo pasa como si se tratase de un ordinario de búfer. Esto funciona y es seguro debido a una matriz dinámica es, en efecto, un subtipo de un viejo y simple de búfer. La función acepta un puntero al primer elemento de la matriz y tratar el puntero como un puntero a un montón de bytes porque eso es exactamente lo que es. La función no necesita saber que pasa a ser cosas adicionales adyacentes a los bytes que utiliza el programa para la dinámica de la matriz de contabilidad.


    Si usted tiene los datos en un búfer y desea para tratar de que búfer como si se fueron la matriz, en lugar de copiar los datos en una estructura de datos, entonces usted tiene dos opciones.

    1. Declarar una estática de la matriz de puntero, y, a continuación, escriba la fundición de su búfer puntero a ese tipo. Esta es la técnica clásica, y usted puede ver que se utiliza en el código de todo el lugar, especialmente el código anterior en Delphi 4. Por ejemplo:

      type
        PByteArray = ^TByteArray;
        TByteArray = array[0..0] of Byte;
      var
        ByteArray: PByteArray;
      
      ByteArray := PByteArray(Output);
      for i := 0 to Pred(OutputLength.Value) do begin
        {$R- }
        edtString.Text := edtString.Text + Chr(ByteArray[i]);
        {$R+}
      end;

      La $R directivas para asegurarse de que la comprobación del rango está desactivada para que el código ya que el tipo de matriz se declara una longitud de 1. La matriz se declara con ese tamaño, en parte, para servir como un indicio de que usted está realmente no se debe declarar una variable de ese tipo. Sólo lo uso a través de un puntero. Por otro lado, si usted sabe lo que un adecuado tamaño máximo de los datos será, puede utilizar ese tamaño para declarar el tipo de matriz en su lugar, y entonces usted puede mantener el intervalo de comprobación de encendido. (Si usted normalmente mantener intervalo de comprobación de movilidad, sólo estás buscando problemas.)

    2. Declarar su buffer como PByte en lugar de Pointer y, a continuación, utilizar Delphi nueva (como los de Delphi 2009) apoyo para el tratamiento arbitrario de los tipos de puntero como el array de punteros. En versiones anteriores, sólo PChar, PAnsiChar, y PWideChar apoyaron esta sintaxis. Por ejemplo:

      var
        Output: PByte;
      
      for i := 0 to Pred(OutputLength.Value) do begin
        edtString.Text := edtString.Text + Chr(Output[i]);
      end;

      La $POINTERMATH directiva de compilador no es necesaria para habilitar esta característica para PByte porque ese tipo es declarado mientras que la directiva es, en efecto. Si usted desea hacer la C-como operaciones de puntero con otros tipos de puntero, a continuación, coloque {$POINTERMATH ON} antes de que el código que hace uso de la nueva sintaxis extendida.


    Como nota final, no es necesario construir sus cadenas de un carácter a la vez. Es un desperdicio en dos maneras. En primer lugar, usted está construyendo una gran cantidad de cadenas de caracteres, cada uno de sólo dos bytes más grande que el anterior. Segundo, ya que está almacenada la cadena de resultado en un control de edición, estás forzando el sistema operativo de la implementación de ese control para asignar un montón de nuevas cadenas, demasiado. Pon tus datos en uno cadena y, a continuación, agregue todos a la vez en el control de edición:

    var
      OutputString: AnsiString;
    
    SetString(OutputString, PAnsiChar(Buffer), OutputLength.Value);
    edtString.Text := edtString.Text + OutputString;
    • Mover(Fuente^, Destino[0], SourceSize); yo había usado este cuando estaba haciendo la matriz estática, pero cuando me cambié a la dinámica de la que no podía acceder a los valores. Pero he leído el artículo que tiene un montón de lo que es ur diciendo. Voy a mirar en estas respuestas y tratar de mejorar la de la aplicación que funciona.
    • Una cosa que usted ha mencionado que se refiere a lo que el artículo menciona no es el uso de getmem. Bien el artículo no menciona el uso de ambos obtienen el mem y longitud, pero la situación fue a la inversa (de la Matriz de puntero). Cuando yo escribí por primera vez la app, yo no uso getmem trabajó pero tenía errores.
  2. 0

    Nevermind… lol después de 2 horas y media de joder con esto finalmente lo entendí algo…. Es un poco desordenado de las cosas que he intentado, pero su trabajo también.

        type
      PDynByteArray = ^TDynByteArray;
      TDynByteArray = array of byte;
    
    procedure TfrmMain.btnQueryClick(Sender: TObject);
    var
      Output: Pointer;
      OutputData: PDynByteArray;
      WorkingData: Array of byte;
      DriveLetter: ShortString;
      I: Integer;
      HexOutput: String;
    begin
    edtSTRING.Clear;
    memHEX.Clear;
    GetMem(Output, OutputLength.Value);
    DriveLetter := edtDrive.Text;
    if SendPSPQuery(Char(DriveLetter[1]), cbxQuery.Items.IndexOf(cbxQuery.Text), Output, OutputLength.Value) = 0 then
      begin
        //Move(Output^,OutputData,56);
        OutputData := PDynByteArray(@Output);
        for I := 0 to OutputLength.Value - 1 do
        begin
          edtString.Text := edtString.Text + Char(OutputData^[I]);
        end;
        for I := 0 to OutputLength.Value - 1 do
        begin
          HexOutput := HexOutput + InttoHex(OutputData^[I],2) + ' ';
        end;
        memHex.Lines.Append(HexOutput);
        FreeMem(Output);
        memHex.SelStart := 0;
      end
    else edtSTRING.Text := 'SCSI Command Failed';
    end;
  3. 0

    Puede utilizar PByte. Con {$POINTERMATH EN} la directiva puede utilizar este puntero como una matriz de bytes.

    {$POINTERMATH ON}
    var
      Output: Pointer;
      ar: PByte;
    begin
      GetMem(Output, 100);
      ar:=Output;
      ShowMessage(IntToStr(ar[0])+IntToStr(ar[1])+'...');
    end;
    • Gracias, se tendrán en él. Mi máximo de salida es de 65536 y el dibujo se tarda un poco, a pesar de 128 es un poco instantánea y eso es todo de mi comandos devuelven desde el dispositivo en este momento.
  4. 0

    En cualquier caso, la razón de la salida de dibujo toma tiempo, es porque usted está buscando en la edtString.texto de la asignación. Este debe ser asignado solamente una vez, no en un bucle. Cada vez que reasignar, muchos niveles de material a ser procesado, a partir de la concatenación de cadenas de todo el camino hacia el SO de dibujo en la pantalla. Usted puede construir una cadena de primero y, a continuación, simplemente asignar al final en el peor de los casos.

Dejar respuesta

Please enter your comment!
Please enter your name here