AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Win32 DLL erstellen

Ein Thema von bdaehn · begonnen am 29. Apr 2005 · letzter Beitrag vom 2. Mai 2005
Antwort Antwort
bdaehn

Registriert seit: 22. Jan 2004
Ort: Wiesbaden
9 Beiträge
 
Delphi 7 Enterprise
 
#1

Win32 DLL erstellen

  Alt 29. Apr 2005, 14:37
Hallo,

ist schon eine Weile her, dass ich mit Delphi mal was gemacht habe und im Moment komme ich bei folgendem Problem nicht weiter:

Ich wuerde gerne ein Extension-DLL fuer einen virtuellen Drucker-Treiber mit Delphi ertellen - Win32 DLL mit Unicode Support - habe angefangen, das entsprechende C-Headerfile umzusetzen, aber irgdendwie scheint das ganze nicht zu funktionieren.
Hier das C-Headerfile:

Delphi-Quellcode:
enum
{
    SC_OUTPUT_BLACKWHITE = 1,
    SC_OUTPUT_GRAYSCALE,
    SC_OUTPUT_COLOR,
}
;

enum
{
    SC_TIFTYPE_NONE = 1,
    SC_TIFTYPE_PACKBITS,
    SC_TIFTYPE_CCITT_HUFFMAN,
    SC_TIFTYPE_CCITT_T4,
    SC_TIFTYPE_CCITT_T6,
    SC_TIFTYPE_JPEG,
}
;

typedef struct _SCJOBINFO
{
   // Form name
    TCHAR formName[32];
   
    // Only values between 100 to 300 dpi are accepted
    int printQuality;

    // One of SC_OUTPUT_BLACKWHITE to SC_OUTPUT_COLOR 
    int colorType;

    // Only values between 1 to 100 are accepted.
    // Higher value means better quality.
    int jpegQuality;

    // One of SC_TIFTYPE_NONE to SC_TIFTYPE_JPEG.
    // PackBits and one of the CCITT types are only applicable if colorType
    // is set to SC_OUTPUT_BLACKWHITE.
    int tiffCompression;

    // Only applicable if tiffCompression is set to SC_TIFTYPE_JPEG.
    // Only values between 1 to 100 are accepted.
    // Higher value means better quality.
    int tiffQuality; 

    // Only values between 1 to 100 are accepted.
    // Higher value means better quality.
    int pdfQuality;
}

SCJOBINFO;

enum
{
    SC_BMP = 1,
    SC_PNG,
    SC_JPG,
    SC_TIF_SINGLE,
    SC_PDF_SINGLE,
    SC_TIF_MULTIPLE,
    SC_PDF_MULTIPLE,
}
;

typedef struct _SCFILEINFO
{
    // Output filename without extension. This parameter is required.
    wchar_t name[MAX_PATH];
   
    // Extension of output filename. This parameter is optional.
    // If none is supplied, a default extension will be used.
    wchar_t ext[MAX_PATH];
   
    // Output image type, which could be one of SC_BMP to SC_PDF_MULTIPLE. <tt>SC_PDF_MULTIPLE</tt>.
    // This parameter is required.
    int type;
}

SCFILEINFO;

typedef BOOL (WINAPI *SCGETJOBINFOFUNC) (SCJOBINFO*);
typedef BOOL (WINAPI *SCGETSAVEFILENAMEFUNC) (SCFILEINFO*);
typedef void (WINAPI *SCENDOFJOBFUNC) ();

Hier, was ich bislang gemacht habe:
Delphi-Quellcode:
library dll;


uses
  ShareMem, SysUtils, Classes, Windows, Messages, Controls, Forms, Dialogs, StdCtrls, ExtCtrls;


{$R *.res}

const
  REGROOT = 'Software\\bdaehn\\SoftCopy';

type
  SCJOBINFO = record
    formName: Array[0..32-1] of CHAR;
    printQuality: Integer;
    colorType: Integer;
    jpegQuality: Integer;
    tiffCompression: Integer;
    tiffQuality: Integer;
    pdfQuality: Integer;
end;



type
  SCFILEINFO = record
    name: Array[0..MAX_PATH-1] of WCHAR;
    ext: Array[0..MAX_PATH-1] of WCHAR;
    typ : Integer;
end;



function scGetJobInfo(var test: SCJOBINFO):Bool;
begin
// ShowMessage('buh');
   Result:=True;
end;

function scGetSaveFilename(var test: SCFILEINFO):Bool;
begin
  //ShowMessage('buh');
     Result:=True;
end;

function scEndOfJob():Bool;
begin
// ShowMessage('buh');
     Result:=True;
end;


begin
end.
Code kompiliert, aber ich bekomme bei der Benutzung des Treibers eine "Memory could not be read" Execptions - irgendeine Idee ? Ich gehe einmal davon aus, dass ich etwas grobes falsch mache, was Uebergabe-Parameter und dergleichen angeht. Wichtig ist wohl auch Unicode-Support fuer diese DLL!
Attached ist noch ein Beispiel in C++ ...

Vielen Dank und Gruss
/bjoern
Angehängte Dateien
Dateityp: cpp softcopyex_158.cpp (3,4 KB, 9x aufgerufen)
  Mit Zitat antworten Zitat
Mephistopheles
(Gast)

n/a Beiträge
 
#2

Re: Win32 DLL erstellen

  Alt 29. Apr 2005, 16:32
Code:
typedef BOOL (WINAPI *SCGETJOBINFOFUNC) (SCJOBINFO*);
typedef BOOL (WINAPI *SCGETSAVEFILENAMEFUNC) (SCFILEINFO*);
typedef void (WINAPI *SCENDOFJOBFUNC) ();
Dies entspricht:
Delphi-Quellcode:
type
SCGETJOBINFOFUNC = function(var bla: SCJOBINFO): BOOL; stdcall;
SCGETSAVEFILENAMEFUNC = function(var bla:SCFILEINFO):BOOL; stdcall;
SCENDOFJOBFUNC = procedure(); stdcall;
Viel Erfolg!

Es handelt sich also nur um Typendeklarationen für Funktionspointer. Nicht jedoch um statische Importe!!!

Noch'n Nachtrag: stdcall ist hier ganz wichtig. Delphi übergibt, wie bei VC's fastcall die Parameter zuerst in den Registern und dann auf dem Stack. stdcall benutzt ab dem ersten Parameter den Stack. WINAPI impliziert stdcall!
  Mit Zitat antworten Zitat
NicoDE
(Gast)

n/a Beiträge
 
#3

Re: Win32 DLL erstellen

  Alt 29. Apr 2005, 16:59
Versuch's mit der Übersetzung (bei Unicode musst Du noch 'UNICODE' definieren)
Delphi-Quellcode:
type
  TScColorType = type Longint;
const
  SC_OUTPUT_BLACKWHITE = TScColorType(1);
  SC_OUTPUT_GRAYSCALE = TScColorType(2);
  SC_OUTPUT_COLOR = TScColorType(3);

type
  TScTiffCompression = type Longint;
const
  SC_TIFTYPE_NONE = TScTiffCompression(1);
  SC_TIFTYPE_PACKBITS = TScTiffCompression(2);
  SC_TIFTYPE_CCITT_HUFFMAN = TScTiffCompression(3);
  SC_TIFTYPE_CCITT_T4 = TScTiffCompression(4);
  SC_TIFTYPE_CCITT_T6 = TScTiffCompression(5);
  SC_TIFTYPE_JPEG = TScTiffCompression(6);

type
  PScJobInfoA = ^TScJobInfoA;
  TScJobInfoA = packed record
    formName : array [0..31] of AnsiChar;
    printQuality : Longint;
    colorType : TScColorType;
    jpegQuality : Longint;
    tiffCompression: TScTiffCompression;
    tiffQuality : Longint;
    pdfQuality : Longint;
  end;
  PScJobInfoW = ^TScJobInfoW;
  TScJobInfoW = packed record
    formName : array [0..31] of WideChar;
    printQuality : Longint;
    colorType : TScColorType;
    jpegQuality : Longint;
    tiffCompression: TScTiffCompression;
    tiffQuality : Longint;
    pdfQuality : Longint;
  end;
  PScJobInfo = ^TScJobInfo;
{$IFDEF UNICODE}
  TScJobInfo = TScJobInfoW;
{$ELSE}
  TScJobInfo = TScJobInfoA;
{$ENDIF}

type
  TScFileType = type Longint;
const
  SC_BMP = TScFileType(1);
  SC_PNG = TScFileType(2);
  SC_JPG = TScFileType(3);
  SC_TIF_SINGLE = TScFileType(4);
  SC_PDF_SINGLE = TScFileType(5);
  SC_TIF_MULTIPLE = TScFileType(6);
  SC_PDF_MULTIPLE = TScFileType(7);

type
  TScFileInfo = packed record
    name : array [0..MAX_PATH-1] of WideChar;
    ext : array [0..MAX_PATH-1] of WideChar;
    type_: TScFileType;
  end;

type
  TFNScGetJobInfoFunc = function(var TScJobInfo): BOOL; stdcall; // scGetJobInfo
  TFNScGetSaveFileNameFunc = function(var TScFileInfo): BOOL; stdcall; // scGetSaveFileName
  TFNScEndOfJobFunc = procedure; stdcall; // scEndOfJobFunc
Zitat von bdaehn:
Code kompiliert, aber ich bekomme bei der Benutzung des Treibers eine "Memory could not be read" Execptions - irgendeine Idee ?
Könnte auch mit Initialisierung der Delphi-Runtime in der DLL zu tun habe... aber um das auszuschliessen müsste man eine eigene RTL schreiben...).
Nimm alles aus der Uses-Liste raus was Du nichts brauchst (ShareMem hat in Deiner DLL nichts zu suchen!).
  Mit Zitat antworten Zitat
bdaehn

Registriert seit: 22. Jan 2004
Ort: Wiesbaden
9 Beiträge
 
Delphi 7 Enterprise
 
#4

Re: Win32 DLL erstellen

  Alt 29. Apr 2005, 17:20
Hallo!

Vielen Dank fuer die echt schnell Hilfe!

Ich habe beide Loesungsansaetze probiert - leider noch immer gleicher Effekt - bekomme 3 spoolsv.exe application errors:

"The instruction at "0x00000000" referenced memory at "0x00000000:. The memory could not be "read".

Ich wuerde einmal auf ein Problem mit den Uebergabe-Parametern tippen... Ich habe auch in anderen dll-Beispielen gesehen, dass dort "exports" benutzt wird, um die Symbole/Funktionen zu exportieren - koennte das evtl. ein Problem sein?

Muss man bei einer DLL nicht auch nicht eine Funktion fuer die dll-Einstiegspunkte setzen? Also etwas in der Art?

Delphi-Quellcode:
BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call)
   {
      case DLL_PROCESS_ATTACH:
      case DLL_THREAD_ATTACH:
      case DLL_THREAD_DETACH:
      case DLL_PROCESS_DETACH:
         break;
    }

    return TRUE;
}
Vielen Dank
/bjoern
  Mit Zitat antworten Zitat
NicoDE
(Gast)

n/a Beiträge
 
#5

Re: Win32 DLL erstellen

  Alt 29. Apr 2005, 17:26
Zitat von bdaehn:
"The instruction at "0x00000000" referenced memory at "0x00000000:. The memory could not be "read".
Siehe letztes Kommentar in meinem bearbeiteten Beitrag.

Zitat von bdaehn:
Ich habe auch in anderen dll-Beispielen gesehen, dass dort "exports" benutzt wird, um die Symbole/Funktionen zu exportieren - koennte das evtl. ein Problem sein?
Ja, die drei Funktionen sollten exportiert werden

Zitat von bdaehn:
Muss man bei einer DLL nicht auch nicht eine Funktion fuer die dll-Einstiegspunkte setzen?
Bei Delphi-DLLs ist das
Delphi-Quellcode:
begin
end.
am Ende.
  Mit Zitat antworten Zitat
bdaehn

Registriert seit: 22. Jan 2004
Ort: Wiesbaden
9 Beiträge
 
Delphi 7 Enterprise
 
#6

Re: Win32 DLL erstellen

  Alt 29. Apr 2005, 18:46
Sorry, hatte den letzten Absatz in Deiner Antwort schlichtweg uebersehen!

Nachdem ich exports hinzugefuegt habe und die uses-Klausel bereinigt habe, scheint die dll halbswegs zu funktionieren - zumindest wird beim 1. Aufruf der dll (nachdem der print-service neugestartet wurde) die Funktion "scGetJobInfo()" aufgerufen (anschliessend allerdings nicht mehr, aber das kann auch so gewollt sein; muss ich noch einmal genauer untersuchen) und zum Schluss immer "scEndJob()".
"scGetSaveFilename()" wird scheint hingegen wohl nie ausgerufen zu werden...

Ist denn die Uebersetzung von z.B.

BOOL WINAPI scGetSaveFileName(SCFILEINFO* info) in

function scGetSaveFilename(var test: TScFileInfo):Bool; korrekt - oder muss man hier auch Pointer uebergeben?

Btw. was macht eigentlich ?

TFNScGetJobInfoFunc = function(var TScJobInfo): BOOL; stdcall; Denke, dass das wohl die Art und Weise beinflusst, die die Library gelinkt wird - oder?

Gruss
/bjoern
  Mit Zitat antworten Zitat
NicoDE
(Gast)

n/a Beiträge
 
#7

Re: Win32 DLL erstellen

  Alt 29. Apr 2005, 20:12
Zitat von bdaehn:
Sorry, hatte den letzten Absatz in Deiner Antwort schlichtweg uebersehen!
Ich hatte den Beitrag editiert, da es mir erst hinterher aufgefallen ist.

Zitat von bdaehn:
Ist denn die Uebersetzung von z.B.BOOL WINAPI scGetSaveFileName(SCFILEINFO* info) infunction scGetSaveFilename(var test: TScFileInfo):Bool; korrekt - oder muss man hier auch Pointer uebergeben?
WINAPI ist eine Aufrufkonvention. Es muss also lauten:function scGetSaveFilename(var test: TScFileInfo): LongBool; stdcall; Nebenbei:function scGetSaveFilename(ScFileInfo: PScFileInfo): LongBool; stdcall; ist intern das gleiche wiefunction scGetSaveFilename(var ScFileInfo: TScFileInfo): LongBool; stdcall; Nur, dass man sich bei letzterem darauf verlassen kann, dass die Adresse der Struktur immer gültig ist. Wenn dies nicht der Fall sein sollte (sieht in dem Quellcode nicht danach aus), dann sollte man die erste Varinate der Überszung (mit Pointer) vorziehen und zuerst den Pointer prüfen bevor man die Struktur benutzt...

Zitat von bdaehn:
Btw. was macht eigentlich ?TFNScGetJobInfoFunc = function(var TScJobInfo): BOOL; stdcall;
Das ist nur eine Definition für den Typ einer Funktion. Die Deklaration ist für den Code nicht wichtig. Nur in sofern, dass Dir der Typ als Vorlage für Deine Funktionen dienen soll.

Gruß Nico
  Mit Zitat antworten Zitat
bdaehn

Registriert seit: 22. Jan 2004
Ort: Wiesbaden
9 Beiträge
 
Delphi 7 Enterprise
 
#8

Re: Win32 DLL erstellen

  Alt 1. Mai 2005, 18:33
Hallo!

So sieht der Code nun im Moment aus - hab's sowohl mit Pointern als auch mit Referenzen (var) probiert - immer dergleiche Effekt ( getjobinfo() wird ab und zu mal aufgerufen, getsavefilename() nie und endofjob() immer) - in meinem Demo greife ich auch ueberhaupt noch gar nicht auf die Uebergabewerte zu - gebe ja nur eine Message aus - deshalb denke ich nicht, dass es mit den Uebergabeparametern was zu tun hat.
Noch irgendeine Idee, was faul sein koennte?

Habe mit einer in Visual C++ geschriebenen DLL ueberprueft, dass wirklich alle 3 Funkionen aufgerufen werden...

Delphi-Quellcode:
library softcopyex;


uses
    Windows,Dialogs;

{$R *.res}

{$DEFINE UNICODE}

type
  TScColorType = type Longint;
const
  SC_OUTPUT_BLACKWHITE = TScColorType(1);
  SC_OUTPUT_GRAYSCALE = TScColorType(2);
  SC_OUTPUT_COLOR = TScColorType(3);

type
  TScTiffCompression = Longint;
const
  SC_TIFTYPE_NONE = TScTiffCompression(1);
  SC_TIFTYPE_PACKBITS = TScTiffCompression(2);
  SC_TIFTYPE_CCITT_HUFFMAN = TScTiffCompression(3);
  SC_TIFTYPE_CCITT_T4 = TScTiffCompression(4);
  SC_TIFTYPE_CCITT_T6 = TScTiffCompression(5);
  SC_TIFTYPE_JPEG = TScTiffCompression(6);

type
  PScJobInfoA = ^TScJobInfoA;
  TScJobInfoA = packed record
    formName : array [0..31] of AnsiChar;
    printQuality : Longint;
    colorType : TScColorType;
    jpegQuality : Longint;
    tiffCompression: TScTiffCompression;
    tiffQuality : Longint;
    pdfQuality : Longint;
  end;

  PScJobInfoW = ^TScJobInfoW;
  TScJobInfoW = packed record
    formName : array [0..31] of WideChar;
    printQuality : Longint;
    colorType : TScColorType;
    jpegQuality : Longint;
    tiffCompression: TScTiffCompression;
    tiffQuality : Longint;
    pdfQuality : Longint;
  end;

{$IFDEF UNICODE}
  TScJobInfo = TScJobInfoW;
{$ELSE}
  TScJobInfo = TScJobInfoA;
{$ENDIF}
  PScJobInfo = ^TScJobInfo;

type
  TScFileType = type Longint;
const
  SC_BMP = TScFileType(1);
  SC_PNG = TScFileType(2);
  SC_JPG = TScFileType(3);
  SC_TIF_SINGLE = TScFileType(4);
  SC_PDF_SINGLE = TScFileType(5);
  SC_TIF_MULTIPLE = TScFileType(6);
  SC_PDF_MULTIPLE = TScFileType(7);

type
  PScFileInfo = ^TScFileInfo;
  TScFileInfo = packed record
    name : array [0..MAX_PATH-1] of WideChar;
    ext : array [0..MAX_PATH-1] of WideChar;
    type_: TScFileType;
  end;

function scGetJobInfo(var test: TScJobInfo):LongBool; stdcall;
var temp : String;

begin
  ShowMessage('GetJobInfo()');
  Result:=True;
end;

function scGetSaveFilename(var test: TScFileInfo):LongBool; stdcall;
var temp : String;

begin
  ShowMessage('scGetSaveFilename()');
  Result:=True;
end;

procedure scEndOfJob(); stdcall;
begin
  ShowMessage('scEndOfJob()');
end;

exports scGetJobInfo, scGetSaveFilename, scEndOfJob;

begin
end.
Vielen Dank und Gruss
/bjoern
  Mit Zitat antworten Zitat
Mephistopheles
(Gast)

n/a Beiträge
 
#9

Re: Win32 DLL erstellen

  Alt 1. Mai 2005, 18:39
Ohne die DLL dürfte ab diesem Punkt eine Analyse des Fehlers schwer werden :-\
  Mit Zitat antworten Zitat
NicoDE
(Gast)

n/a Beiträge
 
#10

Re: Win32 DLL erstellen

  Alt 2. Mai 2005, 10:32
Zitat von bdaehn:
in meinem Demo greife ich auch ueberhaupt noch gar nicht auf die Uebergabewerte zu - gebe ja nur eine Message aus - deshalb denke ich nicht, dass es mit den Uebergabeparametern was zu tun hat.
Ich denke doch. Denn wenn Du die Strukturen nicht mit sinnvollen Daten füllst (wie das Beispiel in C), dann ist es nicht verwunderlich, dass die weiteren Callbacks nicht aufgerufen werden...

ps: die Unit Dialogs um eine Nachricht anzuzeigen ist ziemlicher Overhead, nimm einfach MessageBox
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:32 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz