Jump to content


Photo

Modificación a Bitmap en un dll genera ACCESS VIOLATION

DLL BITMAP ACCESS VIOLATION

  • Please log in to reply
5 replies to this topic

#1 Ricardo Mostalac

Ricardo Mostalac

    Newbie

  • Miembros
  • Pip
  • 3 posts

Posted 15 July 2015 - 12:47 PM

Escribí un pequqeño programa que dibuja en un control PAINT un código de barras 2D, el QR. Quiero convertir mi programa a DLL, lo que necesito es exportar una función (GetQRCodeImagen) a la que le paso 3 parámetros, los datos a codificar, el tipo de codificación y el tamaño de la zona segura y la función me debe devolver el HANDLE del bitmap para que otras aplicaciones lo usen y puedan dibujar o imprimir el código.

 

El problema es que, al tratar de establecer el tamaño del Bitmap con el método Setsize (y en general al tratar de acceder a cualquier atributo o método del Bitmap) la DLL envía el error ACCESS VIOLATION.

 

Lo curioso es que el Bitmap no tiene problema al ejecutar el constructor CREATE, es más, después de ejecutar el CREATE verifico que el Bitmap no sea NIL y efectivamente no lo es. No sé porque después del CREATE no puedo acceder a ningún atributo del Bitmap y esto solo ocurre en la DLL, si lo hago en una aplicación normal funciona sin problema.

 

Espero haber explicado el problema correctamente y que alguien pueda darme un "empujoncito" para poder resolver el problema. 


  • 0

#2 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4111 posts
  • LocationMadrid - España

Posted 15 July 2015 - 05:42 PM

Sin código es difícil saber que pasa. Es posible que exista un error al declarar la función o que trates de compartir variables entre aplicaciones con tu dll, esto no se puede hacer, a no ser que sean constantes


Saludos.
  • 0

#3 Ricardo Mostalac

Ricardo Mostalac

    Newbie

  • Miembros
  • Pip
  • 3 posts

Posted 15 July 2015 - 07:50 PM

A continuación el código de la dll:

 


php
  1. library QRCodeLibDinPrj;
  2.  
  3.  
  4. uses
  5.   Windows, Classes, Graphics, QRCodeUnit
  6.   { you can add units after this };
  7.  
  8.  
  9. function GetQRCodeImagen(Text: Pchar; Codificacion, ZonaSegura: Integer): HBitmap; export; stdcall;
  10. var
  11.   QRCodeBitmap: TBitmap;
  12.   QRCode: TRAMLQRCode;
  13.   Row, Column: Integer;
  14. begin
  15.   QRCodeBitmap := TBitmap.Create;
  16.   QRCode := TRAMLQRCode.Create;
  17.   try
  18.     QRCode.Data := Text;
  19.     QRCode.Encoding := TQRCodeEncoding(Codificacion);
  20.     QRCode.QuietZone := ZonaSegura;
  21.  
  22.     QRCodeBitmap.SetSize(QRCode.Rows, QRCode.Columns);
  23.  
  24.     for Row := 0 to QRCode.Rows - 1 do
  25.     begin
  26.       for Column := 0 to QRCode.Columns - 1 do
  27.       begin
  28.         if (QRCode.IsBlack[Row, Column]) then
  29.         begin
  30.           QRCodeBitmap.Canvas.Pixels[Column, Row] := clBlack;
  31.         end else
  32.         begin
  33.           QRCodeBitmap.Canvas.Pixels[Column, Row] := clWhite;
  34.         end;
  35.       end;
  36.     end;
  37.     Result := Bitmap.ReleaseHandle;
  38.   finally
  39.     QRCode.Free;
  40.     QRCodeBitmap.Free;
  41.   end;
  42.  
  43.  
  44. exports GetQRCodeImagen;
  45.  
  46.  
  47. begin

A continuación el código de la aplicación que importa la función de la dll:

 


php
  1. unit qrcodedll;
  2.  
  3.  
  4. {$mode objfpc}{$H+}
  5.  
  6.  
  7. interface
  8.  
  9.  
  10. uses
  11.   Windows, Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  12.   ExtCtrls;
  13.  
  14.  
  15. type
  16.  
  17.  
  18.   { TQRCodeDLLForm }
  19.  
  20.  
  21.   TQRCodeDLLForm = class(TForm)
  22.     ComboBox1: TComboBox;
  23.     Edit1: TEdit;
  24.     Edit2: TEdit;
  25.     Label1: TLabel;
  26.     Label2: TLabel;
  27.     Label3: TLabel;
  28.     Label4: TLabel;
  29.     PaintBox1: TPaintBox;
  30.     procedure ComboBox1Change(Sender: TObject);
  31.     procedure Edit1Change(Sender: TObject);
  32.     procedure Edit2Change(Sender: TObject);
  33.     procedure FormCreate(Sender: TObject);
  34.     procedure FormDestroy(Sender: TObject);
  35.     procedure PaintBox1Paint(Sender: TObject);
  36.   private
  37.     { private declarations }
  38.     QRCodeBitmap: TBitmap;
  39.   public
  40.     { public declarations }
  41.     procedure Update; override;
  42.   end;
  43.  
  44.  
  45.  
  46.  
  47. var
  48.   QRCodeDLLForm: TQRCodeDLLForm;
  49.  
  50.  
  51.   function GetQRCodeImagen(Text: Pchar; Codificacion, ZonaSegura: Integer): HBitmap;
  52.            stdcall; external 'QRCodeLibDinPrj.dll';
  53.  
  54.  
  55. implementation
  56.  
  57.  
  58. {$R *.lfm}
  59.  
  60.  
  61. { TQRCodeDLLForm }
  62.  
  63.  
  64. procedure TQRCodeDLLForm.Edit1Change(Sender: TObject);
  65. begin
  66.   Update;
  67.  
  68.  
  69. procedure TQRCodeDLLForm.Edit2Change(Sender: TObject);
  70. begin
  71.   Update;
  72.  
  73.  
  74. procedure TQRCodeDLLForm.ComboBox1Change(Sender: TObject);
  75. begin
  76.   Update;
  77.  
  78.  
  79. procedure TQRCodeDLLForm.FormCreate(Sender: TObject);
  80. begin
  81.   QRCodeBitmap := TBitmap.Create;
  82.   Update;
  83.  
  84.  
  85. procedure TQRCodeDLLForm.FormDestroy(Sender: TObject);
  86. begin
  87.   QRCodeBitmap.Free;
  88.  
  89.  
  90. procedure TQRCodeDLLForm.PaintBox1Paint(Sender: TObject);
  91. var
  92.   Scale: Double;
  93. begin
  94.   PaintBox1.Canvas.Brush.Color := clWhite;
  95.   PaintBox1.Canvas.FillRect(Rect(0, 0, PaintBox1.Width, PaintBox1.Height));
  96.   if ((QRCodeBitmap.Width > 0) and (QRCodeBitmap.Height > 0)) then
  97.   begin
  98.     if (PaintBox1.Width < PaintBox1.Height) then
  99.     begin
  100.       Scale := PaintBox1.Width / QRCodeBitmap.Width;
  101.     end else
  102.     begin
  103.       Scale := PaintBox1.Height / QRCodeBitmap.Height;
  104.     end;
  105.     PaintBox1.Canvas.StretchDraw(Rect(0, 0, Trunc(Scale * QRCodeBitmap.Width), Trunc(Scale * QRCodeBitmap.Height)), QRCodeBitmap);
  106.   end;
  107.  
  108.  
  109. procedure TQRCodeDLLForm.Update;
  110. var
  111.   x: Integer;
  112. begin
  113.   x := GetQRCodeImagen(PChar(Edit1.Text), ComboBox1.ItemIndex, StrToIntDef(Edit2.Text, 4));
  114.   ShowMessage(IntToStr(x));
  115.  QRCodeBitmap.Handle := GetQRCodeImagen(PChar(Edit1.Text), ComboBox1.ItemIndex, StrToIntDef(Edit2.Text, 4));
  116.  PaintBox1.Repaint;
  117.  
  118.  

En la dll, con letra BOLD, el código QRCodeBitmap.Setsize (QRCode.Rows, QRCode.Columns), genera el error ACCESS VIOLATION, pero solo en la dll, si la función la compilo en una aplicación de escritorio funciona correctamente.

 

Espero que esto sirva para el "empujoncito" que solicito.

 

Saludos cordiales a todos.


  • 0

#4 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6295 posts
  • LocationArgentina

Posted 15 July 2015 - 07:53 PM

Escribí un pequqeño programa que dibuja en un control PAINT un código de barras 2D, el QR. Quiero convertir mi programa a DLL, lo que necesito es exportar una función (GetQRCodeImagen) a la que le paso 3 parámetros, los datos a codificar, el tipo de codificación y el tamaño de la zona segura y la función me debe devolver el HANDLE del bitmap para que otras aplicaciones lo usen y puedan dibujar o imprimir el código. 

 

No entiendo. ¿Al final quien "pinta"? ¿Tu programa o un tercero?

Comenzaste diciendo que tu aplicación tiene la función de pintar o dibujar códigos de barras y/o QR.

Pero al final te contradices y dices que son las otras aplicaciones las que lo dibujan.


  • 0

#5 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6295 posts
  • LocationArgentina

Posted 15 July 2015 - 08:21 PM

Tendría que darle una repasada al TBitmap. Yo empleo otro componente para el tratamiento de imágenes (el TBGRABitmap) y me he acostumbrado a él.

Que falle en "modo dll" y no en la aplicación es para examinarlo más de cerca. Admito que tendría que repasar que limitaciones hay cuando se está diseñando una dll (hace tiempo que no hago una).

 

Al código que has puesto lo tengo que ver detenidamente. Lo que me llama poderosamente la atención es el método Update. En él invocas a la función 2 veces, la primera para mostrar el handle como valor numérico y la segunda para asociarlo al handle del bitmap.

Siento que te estás complicando innecesariamente.

 

Si no es mucha molestia, y se me permite un poco de crítica constructiva ¿Y cual es el objetivo de que sea por dll? ¿Tienes pensado hacer varias aplicaciones diferentes que hagan uso de dicha biblioteca? Porque si es para una única, y por tanto propia aplicación no tiene sentido. ¿Que esperas al hacerlo dll? ¿Que aplicaciones de tercero (que no sea tuyas) tendrán interés en usar TU DLL? ¿Hay alguna?

Piensa primero si realmente vale la pensa.

 

Otra cuestión, si la dll es quien asume el control de pintar en un handle, lo correcto no es que devuelva uno. Mas bien que reciba uno y pinte en él.

 

Saludos,


  • 0

#6 Ricardo Mostalac

Ricardo Mostalac

    Newbie

  • Miembros
  • Pip
  • 3 posts

Posted 15 July 2015 - 08:30 PM

Hola, tienes razón en cuanto a la doble invocación, esta así porque he estado haciendo pruebas y olvidé quitar una de ellas antes de pegar el código en mi mensaje. El procedure debe quedar de la siguiente manera:


php
  1. procedure TQRCodeDLLForm.Update;
  2. begin
  3.  QRCodeBitmap.Handle := GetQRCodeImagen(PChar(Edit1.Text), ComboBox1.ItemIndex, StrToIntDef(Edit2.Text, 4));
  4.  PaintBox1.Repaint;

Esto es un requerimiento de un cliente. El cliente quiere una dll que le entregue la imagen de un código QR. La dll la va a utilizar desde ABAP en un SMART FORM.


  • 0





Also tagged with one or more of these keywords: DLL, BITMAP, ACCESS VIOLATION

IP.Board spam blocked by CleanTalk.