PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : DLL-Wrapper via DLL?


aths
2011-11-22, 15:39:21
Ich versuche gerade, auf die NVAPI via Delphi zuzugreifen. Im Netz gibt es eine nvapi.pas, welche eine Unit bereitstellt, welche einige API-Funktionen zur Verfügung stellt. Leider ist diese Datei veraltet und/oder unvollständig. Ich scheine es nicht hinzukriegen, neue Funktionen, die ich in der nvapi.h lese, zu implementieren. Offenbar muss man sich für diese auch die Einsprungadressen über eine spezielle NVAPI-Routine holen. Dazu sind irgendwelche ID-Werte erforderlich. Zu wissen, wie man an die ID-Werte für Funktionen einer DLL kommt, würde mir weiterhelfen.

Meine Alternativ-Idee ist, mit C (genauer gesagt, MS Visual C++ 2010 Express) zu versuchen, auf die NVAPI zuzugreifen. Mit mit Visual C++ Express kan man offenbar DLLs erstellen, da müsste ich mich einarbeiten. Kann man aber DLLs erstellen die wiederum andere DLLs benutzen, so dass ich einen Wrapper schreiben könnte den ich dann in Delphi einbinde?

PatkIllA
2011-11-22, 17:59:27
Die meisten dlls benutzen andere dlls und deren Funktionen mehr oder weniger direkt weitergeben.
Klingt für mich aber nur danach, als ob das Problem eine Ebene verschiebst.

Demirug
2011-11-22, 18:28:39
Das müssten die Nummer aus der Exporttabelle sein. Kann Delphi nicht über den Namen binden? Über die Nummern macht man eigentlich schon seit Jahren nicht mehr.

Egal. Damit http://www.dependencywalker.com/ kann man die Nummern heraus bekommen.

aths
2011-11-22, 18:58:16
Danke, das schaue ich mir morgen an.

Im fertigen File was ich downgeloadet hatte (ist auf Arbeit, nicht hier am Heim-PC) werden die Funktionen als Delphi-Funktion mit dem Zusatz cdecl deklariert, aber das ist nicht alles. In der NVAPI-Initialisierungs-Prozedur werden noch mal Handles über eine NVAPI-Prozedur geholt ("nvapi_QueryInterface"). Ich weiß nicht ob das Standard bei DLLs ist oder ob das eine Methode von NV ist, die Funktionen nach Möglichkeit zu verstecken und den Entwickler abhängig vom Erhalt des Headerfiles zu machen. Jedenfalls brauchen die Funktionsnamen dafür noch eine ID. Mal sehen wie weit ich morgen mit dem Depedencywalker komme.

edit: Morgen poste ich mal einen Ausschnitt aus dem Delphi-Quellcode. Eine vergleichbare Routine habe ich im Header-File im NVAPI-SDK leider nicht gefunden.

Die meisten dlls benutzen andere dlls und deren Funktionen mehr oder weniger direkt weitergeben.
Klingt für mich aber nur danach, als ob das Problem eine Ebene verschiebst.Das Problem ist im Moment dass ich den Zugriff auf die API in Delphi kaum nachprogrammiert bekomme, obwohl ich als Vorlage eine Unit im Quellcode habe, wo einige Funktionen für Delphi umgesetzt sind. Das Problem ist einerseits, dass das Headerfile aus dem ich weitere Funktionen für Delphi verfügbar machen möchte, wesentlich komplexere Structs nutzt als im fertigen Delphi-Beispiel-Code und zweitens die Deklaration der einzelnen Routinen seltsam ist. Bevor ich wirklich darangehe, einen Wrapper zu schreiben, würde ich versuchen, direkt aus Delphi einen Zugriff zu bekommen. Leider ist die DDL-Nutzung für mich komplett neu, die Windows-API-Funktionen die ich bislang in Delphi nutze, werden mit mitgelieferten Units direkt verfügbar gemacht.

Demirug
2011-11-22, 19:04:38
Ja, das macht man um die Funktionen zu verstecken weil die Exporttabelle eben jeder auslesen kann. Wie man solche Funktionen in Delphi dann nutzen kann weiß ich allerdings nicht da ich das Interop dort nicht kenne.

aths
2011-11-22, 19:23:00
Müsste ich die IDs dann nicht im offiziellen Header-File finden, oder nutzt er stattdessen die Lib-Datei? (Ich weiß leider nicht, wofür genau Lib-Dateien da sind.)

Demirug
2011-11-22, 19:52:52
Mit dem Tool kannst du schauen was die DLL offiziell exportiert. Alles was es nicht findet geht nur über den internen Mechanismus von nVidia. In wie weit der sich mit Delphi realisieren lässt weiß ich. Du brächtest dann eine DLL welche dir die nv Funktionen so exportiert das sie aus Delphi genutzt werden können. Wenn du das machst würde ich aber vorher nochmal in der Lizenz nachschauen ob das nicht verboten ist weil du ja damit die eigentlich privaten Funktionen öffentlich machst.

Lib Dateien für DLLs enthalten im Prinzip nur das was der Compiler braucht um die Funktionen in der DLL automatisch einbinden zu können. Ohne Lib Datei muss man das alles von Hand machen was etwas mühselig ist.

Exxtreme
2011-11-22, 21:02:24
Ein Beispiel wie man aus Delphi/Lazarus eine Funktion einer DLL lädt:
http://de.wikipedia.org/wiki/Dynamic_Link_Library#Eine_DLL_einbinden_.2F_aufrufen


Man muss halt den Namen der Funktion kennen. Oder die ID genannt Ordinal. Hier mal ein Beispiel wie man so einen Aufruf per Ordinal in Delphi durchführt:
https://forums.embarcadero.com/message.jspa?messageID=296340

aths
2011-11-22, 21:32:44
So weit bin ich im Prinzip schon. Das Problem bei mir ist etwas anders. Ich poste morgen ein paar Zeilen Delphi-Code um das Problem hier im Thread konkreter zu beschreiben.


Mit dem Tool kannst du schauen was die DLL offiziell exportiert. Alles was es nicht findet geht nur über den internen Mechanismus von nVidia. In wie weit der sich mit Delphi realisieren lässt weiß ich. Du brächtest dann eine DLL welche dir die nv Funktionen so exportiert das sie aus Delphi genutzt werden können. Wenn du das machst würde ich aber vorher nochmal in der Lizenz nachschauen ob das nicht verboten ist weil du ja damit die eigentlich privaten Funktionen öffentlich machst.

Lib Dateien für DLLs enthalten im Prinzip nur das was der Compiler braucht um die Funktionen in der DLL automatisch einbinden zu können. Ohne Lib Datei muss man das alles von Hand machen was etwas mühselig ist.Die Unit die ich als Quellcode habe, scheint das alles von Hand zu machen. Wenn ich die NVAPI wrappen würde, würde ich vermutlich nicht die Originalfunktionen wrappen sondern es so gestalten, nur Funktionswerte (statt Pointers auf Structs) zu bekommen. Es stimmt aber dass ich nachlesen sollte, ob so eine DLL überhaupt rausgegeben werden darf. Im Moment brauchen wir es nur intern, da besteht auch keine Gefahr, dass das an die Öffentlichkeit gerät. Die Rechner haben nicht mal Internet- oder auch nur LAN-Verbindung :)

Kann man ein Projekt bei gängigen Programmiersprachen so kompilieren dass eine DLL direkt in die Exe-Datei gepackt wird?

aths
2011-11-23, 10:06:59
Zu den Code-Schnipseln: Das steht "Header translation by (2008) Andreas Hausladen", er übersetzte die Nicht-NDA-Version eines älteren NVAPI-SDKs nach Delphi. Diese Routine habe ich im Embarcadero-Developer-Bereich gefunden.


const
NvAPIFunctions: array[0..63] of TNvAPIFuncRec = (
(ID: $6C2D048C; Func: @@NvAPI_GetErrorMessage),
(ID: $01053FA5; Func: @@NvAPI_GetInterfaceVersionString),
(ID: $F951A4D1; Func: @@NvAPI_GetDisplayDriverVersion),
[... weitere Einträge folgen]


Folgenden Code habe ich der Übersicht halber um Deklarationen und einige Fehlerbehandlungsroutinen gekürzt, um den Blick auf das Wesentliche zu lenken.


function NvAPI_Initialize;
const
NvAPILib = 'nvapi.dll';
NvAPI_ID_INIT = $0150E828;
var
[...]
begin
Lib := LoadLibrary(NvAPILib);
begin
nvapi_QueryInterface := GetProcAddress(Lib, 'nvapi_QueryInterface');
if Assigned(nvapi_QueryInterface) then
begin
InitFunc := nvapi_QueryInterface(NvAPI_ID_INIT);
if Assigned(InitFunc) then
begin
if InitFunc() >= 0 then
begin
{ Initialize all function pointers }
Rec := @NvAPIFunctions;
while Rec.ID <> 0 do
begin
P := nvapi_QueryInterface(Rec.ID);
if P <> nil then
PPointer(Rec.Func)^ := P;
Inc(Rec);
end;
Result := NVAPI_OK;
end;
end;
end;
end
Initialized := Result = NVAPI_OK;
end;


Wenn ich das richtig sehe, holt die Routine die Einsprung-Adressen für die NVAPI-Funktionen und benötigt dazu die im ersten Code-Schnipsel angegebenen IDs. Hat jemand eine ID wie man die ID für eine Funktion bekommt? Müsste man dazu in die Lib-Datei gehen?

Exxtreme
2011-11-24, 22:14:10
Über die IDs zu gehen ist nicht so gut. Denn die können sich mit neuen Versionen der DLL ändern. Man ist früher über die IDs gegangen weil es schneller ist da eine Zahl zu vergleichen weniger aufwändig ist als ein Zeichenkettenvergleich.

Wie man die IDs herbekommt weiss ich nicht.

Nagelbrett
2011-11-24, 23:40:45
So wie ich das sehe, kommt man beim dynamischen Laden ohne die .lib zu linken nicht drum rum, diese IDs zu verwenden, welche man an nvapi_QueryInterface übergeben muss. Die Funktionen werden ja nicht direkt exportiert.
Vermutlich hat die IDs mal irgend jemand reverse engineered, denn von nVidia bekommt man sie ja anscheinend nicht, aber viele findet man im Netz (und man könnte hoffen, dass sie sich nicht ändern, auch wenn man davor natürlich nicht 100% sicher ist.)

aths
2011-11-24, 23:44:09
Diese IDs die hier genutzt werden, sind offenbar Codes um die nvapi_QueryInterface-Schnittstelle zu überreden, die richtigen Adressen zurückzugeben. Das wird sich vermutlich nicht mit neuen DLLs ändern da dann Tools die auf die NVAPI setzen, nicht mehr funktionieren würden wenn sie nicht mit dem neuen Header compiliert würden.