PDA

View Full Version : Trying to pass my own filepath in order to load a dll.



Grendelus
12-01-2007, 07:19 PM
library display;

uses
Windows,
SysUtils;

procedure SetResolution(HorizR:Integer;VertR:Integer;AddR:In teger) cdecl;
external 'Resolution.dll' name 'SetResolution';


function _set320x240:PChar; cdecl;
begin
SetResolution(320,240,4);
end;

function _set640x480:PChar; cdecl;
begin
SetResolution(640,480,4);
end;

function _set800x600:PChar; cdecl;
begin
SetResolution(800,600,4);
end;

function _set1024x768:PChar; cdecl;
begin
SetResolution(1024,768,4);
end;

function _set1280x1024:PChar; cdecl;
begin
SetResolution(1280,1024,4);
end;

function _set1600x1200:PChar; cdecl;
begin
SetResolution(1600,1200,4);
end;

function _set1280x800:PChar; cdecl;
begin
SetResolution(1280,800,4);
end;

function _set1024x600:PChar; cdecl;
begin
SetResolution(1024,600,4);
end;

function _set1366x768:PChar; cdecl;
begin
SetResolution(1366,768,4);
end;

exports _set320x240;
exports _set640x480;
exports _set800x600;
exports _set1024x768;
exports _set1280x1024;
exports _set1600x1200;
exports _set1280x800;
exports _set1024x600;
exports _set1366x768;

begin end.

Here you go. This is a wrapper dll I made for a resolution change dll.
The problem is that I want the 'resolution.dll' path and filename to be able to change dynamically by passing my own filepath as a string.

e.g.

procedure SetResolution(HorizR:Integer;VertR:Integer;AddR:In teger) cdecl;
external 'Resolution.dll' name 'SetResolution';

to something like:

var dllName:String;

procedure SetResolution(HorizR:Integer;VertR:Integer;AddR:In teger) cdecl;
external dllName name 'SetResolution';
The above does not work. :(

Nitrogen
12-01-2007, 07:44 PM
That syntax is for a statically linked DLL. ie. you cant change it at runtime.

For a dynamically linked DLL use this code:

procedure TForm1.Button1Click(Sender: TObject);
Var LibName: string;
LibHandle: THandle;
MyFunction: Function(a,b: integer): boolean;
begin

LibName := 'myplugin.dll'

LibHandle := LoadLibrary(pansichar(Libname));
if LibHandle <> 0 then
MyFunction := GetProcAddress(LibHandle, 'MyFunctionName');

//Use MyFunction here!!
MyFunction(10, 20);


FreeLibrary(LibHandle);
//You can no longer use MyFunction after freeing the library.
end;

Nitrogen
13-01-2007, 10:14 AM
I've uploaded a Plugin DLL Demo to my website.

It shows dynamically loading DLLs, displaying forms from a DLL and sharing data and classes between DLL and the main app.

www.nitrogen.za.org

NecroDOME
13-01-2007, 12:23 PM
const DLL_NAME = 'MyPath\MyDll.dll'

Grendelus
21-01-2007, 09:44 PM
That syntax is for a statically linked DLL. ie. you cant change it at runtime.

For a dynamically linked DLL use this code:

[pascal:1:9ee0a51a59]procedure TForm1.Button1Click(Sender: TObject);
Var LibName: string;
LibHandle: THandle;
MyFunction: Function(a,b: integer): boolean;
begin

LibName := 'myplugin.dll'

LibHandle := LoadLibrary(pansichar(Libname));
if LibHandle <> 0 then
MyFunction := GetProcAddress(LibHandle, 'MyFunctionName');

//Use MyFunction here!!
MyFunction(10, 20);


FreeLibrary(LibHandle);
//You can no longer use MyFunction after freeing the library.
end;
[/pascal:1:9ee0a51a59]

Thanks man, I was finally able to do it.

AthenaOfDelphi
17-03-2007, 07:25 PM
I've uploaded a Plugin DLL Demo to my website.

It shows dynamically loading DLLs, displaying forms from a DLL and sharing data and classes between DLL and the main app.

www.nitrogen.za.org

Hi Nitrogen,

This doesn't work with Delphi 5, because of the Application/DLL boundary stripping off RTTI, but it works just fine with BDS 2006 (about time they fixed it), but do you (or does anyone else) know whether it works with FreePascal?

Edit:- Actually I think this is a largely redundant question, because I'm guessing that the internal workings of FreePascal's objects are subtly different to those of Delphi and so the two wouldn't be compatible even if they got passed over the app/dll boundary.

Chebmaster
20-03-2007, 04:30 PM
I'm guessing that the internal workings of FreePascal's objects are subtly different to those of Delphi and so the two wouldn't be compatible even if they got passed over the app/dll boundary.
I use the dynamic DLLs a lot, so I could say: this *could* work and work well (even if the EXE is compiled in Delphi while DLL is in FReePascal)... BUT. You should pay a lot of attention, since your EXE and your DLL do *have separate memory managers*! (I heard there is a whole way around that, ShareMem, but I never used it so I can't say).

Even something as innocious as passing a string parameter could be your undoing! Not to say about classes. Because each module thinks that it was it who allocated the memory... And in a lot of caes it tries silently to re-allocate it, leading to memory corruption.

So, as a rule of thumb: never use strings and dynamic arrays to communicate between your DLL and your EXE! You can always resort to pointers and integers. In fact, each time I need to pass a string I convert it to PChar, and reconstruct on the receiving end by copying into a string. Seems slow?.. But my engine works like a clock, even with a lot of its operations scattered around the EXE/DLL boundary.

In fact, the only problems I encountered with a half of my engine compiled in Delphi and other half in FreePascal was the exception handling. The app just summoned up a standard windows postmortem dialog instead of reporting the error by itself, as designed.

AthenaOfDelphi
20-03-2007, 05:10 PM
Thanks Chebmaster, Technomage has confirmed what you've said about shared memory following my post about the issue in the 'Help Me' forum.

Been experimenting, quite successfully to an extent, but it now appears I'm going to be forced to use a shared memory manager as it all just goes horribly wrong once memory has been allocated on both sides of the boundary.

Oh well.. small price to pay :-)