nova2002
asked on
Creating DLL for Delphi
Hi,
Anyone have any GOOD resources / examples about creating/accessing DLL for Delphi ?
I just want to learn it to create something like "plugin" feature for my application.
Thanks in advance.
Regards,
nova
Anyone have any GOOD resources / examples about creating/accessing DLL for Delphi ?
I just want to learn it to create something like "plugin" feature for my application.
Thanks in advance.
Regards,
nova
Hi Nova,
If you check out this link on delphi.about.com, It's good a good beginners article on making a simple dll.
http://delphi.about.com/library/weekly/aa041100a.htm
Cheers,
whos_wee_dug
If you check out this link on delphi.about.com, It's good a good beginners article on making a simple dll.
http://delphi.about.com/library/weekly/aa041100a.htm
Cheers,
whos_wee_dug
hello Nova2002, since you seem to be new to making DLL's, here is some code for a very simple DLL and for the program that calls it, I rarely use the stdCall calling convention, brcause I do not need it.
Code for the DLL, notice I do not need the uses clause because I only use basic math operators, but is you use any functions from other units, like SysUtils, you will need a Uses clause -
library Demo1;
procedure MyProcedure(Input: Integer; var Output: Integer); export;
begin
{if you are going to send back a parameter, then you need the var in front}
OutPut := Input * 4;
end;
function MyFunction(Base, Mult: Integer): Integer; export;
begin
Result := Base * Mult;
end;
function StdCallFunc(Input: Integer; var Output: Integer): Integer; stdCall; export;
begin
{the stdCall will tell the compiler to read the Parameters from Right-to-left
instead of the normal Pascal Left-to-right, this stdCall is needed for
a C-Language program, which will read parameters Right-to-left}
Result := ((Input *5) - OutPut) div 2;
OutPut := (Input * 3)+ 20;
{I usually do NOT want my DLL to be used by any other program,
so I do not use the stdCall Calling convention}
end;
exports
MyProcedure,
MyFunction,
StdCallFunc;
begin
end.
- - - - - - - - - - - - - - - - - - - - - - - - -
Here is some code for Two Button Clicks, the first one justs loads the DLL and tests for success, then gets the OutPut value from the MyProcedure. . . .
the second one loads the DLL and does Two functions, one with the stdCall calling convention
procedure TForm1.sbut_LoadDllClick(S ender: TObject);
var
hLib, In1, Out1: Integer;
MyProcedure1: procedure(Input: Integer; var Output: Integer);
begin
hLib := LoadLibrary('Demo1.dll');
if hLib = 0 then
begin
ShowMessage('Error - Did not load the DLL');
Exit;
end;
@MyProcedure1 := GetProcAddress(hLib, 'MyProcedure');
if @MyProcedure1 = nil then
begin
FreeLibrary(hLib);
ShowMessage('ERROR - MyProcedure1 is nil');
Exit;
end;
In1 := 22;
Out1 := 0;
MyProcedure1(In1, Out1);
ShowMessage('Out1 is = '+IntToStr(Out1));
FreeLibrary(hLib);
end;
procedure TForm1.sbut_LoadDll2Click( Sender: TObject);
var
hLib, In1, Out1, DResult: Integer;
MyFunction1: function(Base, Mult: Integer): Integer;
stdCallFunc1: function(Input: Integer; var Output: Integer): Integer; stdCall;
begin
hLib := LoadLibrary('Demo1.dll');
if hLib = 0 then
begin
ShowMessage('Error - Did not load the DLL');
Exit;
end;
@MyFunction1 := GetProcAddress(hLib, 'MyFunction');
if @MyFunction1 = nil then
begin
FreeLibrary(hLib);
ShowMessage('ERROR - MyFunction1 is nil');
Exit;
end;
In1 := 122;
Out1 := 3;
DResult := MyFunction1(In1, Out1);
ShowMessage('Out1 is = '+IntToStr(Out1)+#10'Resul t is = '+IntToStr(DResult));
@stdCallFunc1 := GetProcAddress(hLib, 'StdCallFunc');
if @stdCallFunc1 = nil then
begin
FreeLibrary(hLib);
ShowMessage('ERROR - stdCallFunc1 is nil');
Exit;
end;
DResult := stdCallFunc1(In1, Out1);
ShowMessage('Out1 is = '+IntToStr(Out1)+#10'Resul t is = '+IntToStr(DResult));
FreeLibrary(hLib);
end;
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ask questions if you need more information
Code for the DLL, notice I do not need the uses clause because I only use basic math operators, but is you use any functions from other units, like SysUtils, you will need a Uses clause -
library Demo1;
procedure MyProcedure(Input: Integer; var Output: Integer); export;
begin
{if you are going to send back a parameter, then you need the var in front}
OutPut := Input * 4;
end;
function MyFunction(Base, Mult: Integer): Integer; export;
begin
Result := Base * Mult;
end;
function StdCallFunc(Input: Integer; var Output: Integer): Integer; stdCall; export;
begin
{the stdCall will tell the compiler to read the Parameters from Right-to-left
instead of the normal Pascal Left-to-right, this stdCall is needed for
a C-Language program, which will read parameters Right-to-left}
Result := ((Input *5) - OutPut) div 2;
OutPut := (Input * 3)+ 20;
{I usually do NOT want my DLL to be used by any other program,
so I do not use the stdCall Calling convention}
end;
exports
MyProcedure,
MyFunction,
StdCallFunc;
begin
end.
- - - - - - - - - - - - - - - - - - - - - - - - -
Here is some code for Two Button Clicks, the first one justs loads the DLL and tests for success, then gets the OutPut value from the MyProcedure. . . .
the second one loads the DLL and does Two functions, one with the stdCall calling convention
procedure TForm1.sbut_LoadDllClick(S
var
hLib, In1, Out1: Integer;
MyProcedure1: procedure(Input: Integer; var Output: Integer);
begin
hLib := LoadLibrary('Demo1.dll');
if hLib = 0 then
begin
ShowMessage('Error - Did not load the DLL');
Exit;
end;
@MyProcedure1 := GetProcAddress(hLib, 'MyProcedure');
if @MyProcedure1 = nil then
begin
FreeLibrary(hLib);
ShowMessage('ERROR - MyProcedure1 is nil');
Exit;
end;
In1 := 22;
Out1 := 0;
MyProcedure1(In1, Out1);
ShowMessage('Out1 is = '+IntToStr(Out1));
FreeLibrary(hLib);
end;
procedure TForm1.sbut_LoadDll2Click(
var
hLib, In1, Out1, DResult: Integer;
MyFunction1: function(Base, Mult: Integer): Integer;
stdCallFunc1: function(Input: Integer; var Output: Integer): Integer; stdCall;
begin
hLib := LoadLibrary('Demo1.dll');
if hLib = 0 then
begin
ShowMessage('Error - Did not load the DLL');
Exit;
end;
@MyFunction1 := GetProcAddress(hLib, 'MyFunction');
if @MyFunction1 = nil then
begin
FreeLibrary(hLib);
ShowMessage('ERROR - MyFunction1 is nil');
Exit;
end;
In1 := 122;
Out1 := 3;
DResult := MyFunction1(In1, Out1);
ShowMessage('Out1 is = '+IntToStr(Out1)+#10'Resul
@stdCallFunc1 := GetProcAddress(hLib, 'StdCallFunc');
if @stdCallFunc1 = nil then
begin
FreeLibrary(hLib);
ShowMessage('ERROR - stdCallFunc1 is nil');
Exit;
end;
DResult := stdCallFunc1(In1, Out1);
ShowMessage('Out1 is = '+IntToStr(Out1)+#10'Resul
FreeLibrary(hLib);
end;
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ask questions if you need more information
There is a Plugin component with the Jedi VCL open source component suite that you could use or base your own version off of.
http://jvcl.sourceforge.net/
http://jvcl.sourceforge.net/
Hi Nova2002,
Check out http://www.1delphistreet.com/vb/scripts/ShowCode.asp?txtCodeId=538&lngWId=7 this is a great example of creating/using *.dlls in Delphi
Check out http://www.1delphistreet.com/vb/scripts/ShowCode.asp?txtCodeId=538&lngWId=7 this is a great example of creating/using *.dlls in Delphi
ASKER
Hi,
I tried using Slick182 example, and it's working. But when I 'exported' a function with string parameter and result, I got problem.
In my DLL, I created this function :
function something (s: string) : string;
begin
result := 'hahahahaha';
end;
In my application, I can load the DLL, I can call that function.
But, if I close my application (by clicking 'x'), I got error :
Project DLLDemo.exe raised exception class EInvalidPointer with message "Invalid Pointer Operation".
Anyone how to fix it ? I put "ShareMem" unit on both.
This problem only when I use 'string' ?
Thanks
I tried using Slick182 example, and it's working. But when I 'exported' a function with string parameter and result, I got problem.
In my DLL, I created this function :
function something (s: string) : string;
begin
result := 'hahahahaha';
end;
In my application, I can load the DLL, I can call that function.
But, if I close my application (by clicking 'x'), I got error :
Project DLLDemo.exe raised exception class EInvalidPointer with message "Invalid Pointer Operation".
Anyone how to fix it ? I put "ShareMem" unit on both.
This problem only when I use 'string' ?
Thanks
Replace String with PChar
ASKER
Same result .. I changed it to PCHAR and I still got Invalid Pointer Operation when I closed my application.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
AND. . . you will need to add
uses
SysUtils;
to your library
uses
SysUtils;
to your library
library my_dll;
uses ... ;
procedure Proc1;stdcall;
begin
...
end;
procedure Proc2 ( P1,P2 : PChar );stdcall;
begin
...
end;
function Func1 ( P1 : Integer ) : Integer;stdcall;
begin
...
end;
exports
Proc1 index 0,
Proc2 index 1,
Func1 index 2;
begin
end;
Use a DLL :
....
procedure DllProc1 ( Param1,Param2 : aType ); [stdcall;] external 'dll_file_name.dll';
....
begin
...
DllProc1 ( P1,P2 );
...
end.
stdcall directive is useful, when you will use the dll in another language ( not Delphi )