Call and Reuse the DLL functions dynamically - delphi

I have created a DLL file with some functions and wish to reuse in a program multiple times in its different functions. But the Access-violation error comes after 2nd function of the program when calls the same DLL functions.
I'm currently using GetProcAddress. For example:
function xyz:boolean
var
dllHandle : cardinal;
EnBFStr : TEnBFStr;
StrToHex : TStrToHex;
Encodeddata , HexString : UnicodeString;
begin
dllHandle := LoadLibrary('Utilities.dll') ;
if dllHandle <> 0 then
begin
Encodeddata:='Sample';
#EnBFStr := GetProcAddress(dllHandle, 'EncodeBlowFishString') ;
#StrToHex := GetProcAddress(dllHandle, 'UniStrToUniHexStr') ;
if Assigned (EnBFStr) then
Encodeddata:=EnBFStr('Key','Text') ; //Sample would be replaced
if Assigned (StrToHex ) then
HexString :=StrToHex(Encodeddata) ; //call the function
FreeLibrary(dllHandle) ;
end;
There are other functions which is loading the library and calling these DLL functions multiple times. Also, within the same procedure/function, we are calling these DLL functions multiple times in (IF Else) conditions.
In earlier part of the program, I have tried to check for the DLL file is present. Also, I tried to directly load the functions as another alternative:
function EncodeBlowFishString (Const Key:UnicodeString; Const DecodedString:UnicodeString; ): UnicodeString; stdcall;
external 'Utilities.dll' name 'EncodeBlowFishString';
function UniStrToUniHexStr(Const aString:UnicodeString): UnicodeString; stdcall;
external 'Utilities.dll';

You are breaking the rules of memory allocation for DLLs. The return value is allocated by the callee but deallocated by the caller. Two solutions:
Use ShareMem as described in the comment at the top of a new library project.
Use standard interoperability techniques to ensure that allocation and deallocation always happens in the same module.
As an aside it is greatly wasteful to load and unload a DLL each time you want to use it. Load the DLL once only.
Furthermore I would like to point out that encryption operates on binary data and in my view you are storing up a world of pain by working instead with text.

Related

Dynamicly handle not defined functions in a dll in dlephi

I have a dll which defines a simple functions to show a message:
library testdll;
uses SysUtils, Classes, Dialogs;
{$R *res}
procedure ShowDll;stdcall;
begin
ShowMessage('ShowDLL testdll.dll');
end;
exports ShowDLL;
begin
end.
And my main file call this dll dynamicly using this procedure:
i defined a new type:
type
testdll = procedure;stdcall;
Then on my button click event:
procedure TForm1.Button1Click(Sender:TObject);
var
dllHandle: THandle; //Don't use Cardinal; it's limited to 32-bits
test : testdll;
begin
dllHandle := LoadLibrary('testdll.dll');
if dllHandle <> 0 then
begin
#test := GetProcAddress(dllHandle,'ShowDLL');
if Assigned(test) then
ShowDLL
else
ShowMessage('Func not found');
end
else
ShowMessage('dll not found');
end;
This works. But I don't know if it's possible to handle not defined functions with my dll. My purpose here is to call a function without knowing if it will be defined in my dll. So i would like the dll to tell me if the functions exists or not.
For example here i only have a ShowDLL procedure. If i call another method which does not exists it will show 'Func not found' from my main application. But i would my dll to tell me this. Is this possible? If yes, how could i achieve this pls?
EDIT: I can't modify the main function this is only a test. In my final version there will be only the dll. So exporting all functions into my main application is not possible here. That's why i want to know id the dll alone can handle it rather than doing this in my main application which i can't do.
I don't have acces to the main application to modify any code in it. I only know what are functions that will be used in this application that i will later export in my dll using exports statement. So what i try to achieve is to catch a not defined function with the dll if it's possible.
Your code already demonstrates how to detect the presence of an export. Namely to call GetProcAddress and compare the result with nil.
You can reduce the amount of boiler plate code by using delay loading. This essentially lets the compiler generate the code the performs the checks. This relies on the delayed keyword.
procedure testdll; stdcall;
external 'testdll.dll` delayed;
When you call this function, if it cannot be found, an exception is raised. Indeed this behaviour can be customised, as described in the documentation: http://docwiki.embarcadero.com/RADStudio/en/Libraries_and_Packages#Delayed_Loading
Update
In a comment to this answer you state that the executable cannot be changed. In which case, the message that you wish to avoid will be shown if the function is missing. You ask if the missing export can be handled by the DLL but that is not possible. When you call GetProcAddress, no code inside the DLL is executed. All the processing is done external to the DLL by reading its PE metadata.
The obvious conclusion is that the DLL must export the function. If the true DLL does not, put another DLL in its place. Use an interposer DLL that exports the function. Implement the function by delegating to the true DLL, if the true DLL exports the function. Otherwise do something else, whatever you please.

Work around with Delphi DLL

I have two applications in Delphi for which I don't have any code source:
I use an interface from application A to call an DLL file from application B. Example, I usually pass a service number, 200011, from interface A to call DLL file B for a value return. But, recently the application A have changed the variable. I have to add P00200011 to call DLL file B.
I have tried to create an DLL C#, but the DLL in B is created with the fastcall convention and I cannot change this DLL file.
What are others ways I can do it? I'm out of ideas.
You need to write a wrapper DLL. You build your DLL with the functions you want to intercept, and in your code you simply load and call the original DLL. Then you place your wrapper in the same directory of your application. All calls from the application will go to your wrapper DLL and from there to the original DLL.
Here is a simple example
supose you have this library (B.DLL)
library B;
function B_FUNCTION(value:integer): integer; export;
begin
result:=value+1;
end;
exports B_FUNCTION;
end.
And this program that uses it
program A;
{$apptype console}
function B_FUNCTION(value:integer): integer; external 'b.dll';
var i:integer;
begin
i:=B_FUNCTION(2010);
writeln(i);
end.
Compile both programs and run them. The result printed is 2011.
Now, code your wrapper DLL
library w;
uses windows;
function B_FUNCTION(value:integer): integer; export;
var
adll: Thandle;
afunc: function(v:integer):integer;
begin
adll:=LoadLibrary('TRUE_B.DLL');
afunc:= GetProcAddress(adll,'B_FUNCTION');
result:=afunc(value+1);
FreeLibrary(adll);
end;
exports B_FUNCTION;
end.
Build it, you'll have A.EXE, B.DLL and W.DLL. Replace them
REN B.DLL TRUE_B.DLL
REN W.DLL B.DLL
Execute A, now it will spit 2012.
It's not entirely obvious to me which parts are yours and what calls what, but you should be able to create your own intermediate DLL in Delphi with an interface that uses fastcall and which forwards the call to the real DLL using another calling convention.

Free Pascal can't find entry point for dll

I am complete new to pascal.
I want to call my function in .dll file in free pascal and I get following error when I run the project:
The procedure entry point GetProcAddress could not be located in the dynamic link library HNLib.dll.
here is the code:
Program Test;
function GetProcAddress : Integer; cdecl; external 'HNLib.dll';
function GetProcAddress : Single; cdecl; external 'HNLib.dll';
procedure GetProcAddress( X : Single); cdecl; external 'HNLib.dll';
procedure GetProcAddress; cdecl; external 'HNLib.dll';
begin
GetProcAddress( 5.5 );
readln;
end.
.pas file and dll are in one directory.
Please Help ME!
GetProcAddress is not what you seem to think it is; it's purpose is to locate named procedures or functions in a DLL and return the address of that function so it can be called from your code. You have to first use LoadLibrary to load the dynamic link library (DLL) into memory, and then pass a handle to that DLL as the first parameter of GetProcAddress and the name of the function whose address you want as the second parameter. If the function can be found in the DLL, it's address is returned, and you can use that address to call the function.
(In addition, GetProcAddress is pretty Windows-specific, and the majority of functions in the WinAPI are stdcall and not cdecl. Unless you have documentation saying that the functions are using the cdecl calling convention, you should probably use stdcall.)
You would also need at least the Windows unit in your uses clause, since that's where GetProcAddress and LoadLibrary are declared.
See the WinAPI documentation on LoadLibrary and GetProcAddress for more information.
For a beginning programmer, you'll probably find it easier to use static linking of the functions instead of dynamic (which you get with GetProcAddress). An example of static linking would be (untested !!!- just a quick code example, since I don't have 'HNLib.DLL' to link against):
// Your Dll import unit
unit MyDllProcs;
interface
function GetIntCalcResult(const IntVal: Integer);
implementation
function GetIntCalcResult(const IntVal: Integer); stdcall; external 'HNLib.dll';
end.
// Your own app's code
program Test;
interface
uses MyDllProcs;
implementation
function DoSomethingWithDll(const ValueToCalc: Integer): Integer;
begin
Result := GetIntCalcResult(ValueToCalc);
end;
begin
WriteLn('DoSomethingWithDll returned ', DoSomethingWithDll(10));
ReadLn;
end.
Note that when statically linking DLL functions like this, your DLL must be available when your app starts, and the function must be contained in that DLL; if not, your application won't load.
Also, note that you can't typically have multiple functions with the same name in the DLL, as there's no information available to use to figure which one to load when the load is being done. Each should have a separate, distinct name or the loading will probably fail.

Calling a function in DLL so slow

My program have several worker threads that calling a function in a dynamically loaded DLL file. The performance is slower than calling function in EXE file. My program made using Delphi. I don't use ShareMM. The function in DLL has many routines to read file into memory. The used calling convention is stdcall. Actually, the speed is very poor!
I have no idea since I just learned about using DLL. So what should I do to optimize the performance/speed of my program/DLL?
Sorry if my question is non sense. I am sure there is nothing wrong with my exe, I just moved my functions into DLL and the performance be slower. Please ignore disk/memory cache factor as I have mentioned the routines of my DLL.
Edited:
This is how my program load the DLL
DLLHandle := LoadLibrary(pwchar(path));
if DLLHandle <> 0 then
#CheckFile := GetProcAddress(DLLHandle, 'CheckFile');
In my worker threads, I always check the function using if Assigned(CheckFile) then then call CheckFile function.
Here illustration of my function
type
TCheckFile = function(const FileName: string; var FileType: WideString)
: Boolean; stdcall;
var
CheckFile: TCheckFile ;
Now, the code in DLL
function CheckFile(const FileName: string; var FileType: WideString)
: boolean; stdcall;
var
testCheckFile: TBla;
begin
Result := false;
testCheckFile := TBla.Create;
try
if testCheckFile.DoSomeRoutine(FileName, FileType) then
Result := true;
finally
testCheckFile.Free;
end;
end;
exports CheckFile;
begin
IsMultiThread := true;
end.
What my DLL do? It plays with TFileStream like convert file to pointer.
I hope there is something wrong with my loading code and the calling code.
Code that resides in a DLL runs at just the same speed as code that resides in the host executable. It is exceedingly unlikely that moving code to a DLL will result in a discernible drop in performance.
However, you state in comments to the question that you have also ported from Delphi 2007 to Delphi XE2. That is almost certainly the change that resulted in the performance drop.
When measuring and comparing performance it is simply crucial to change one thing at a time so that you remove any possibility for confounding factors.
Maybe the problem is having to do with: " dynamically loaded DLL file". Dynamic is ok, but once you load it, keep it loaded right? If you keep loading/unloading for every function call, it's going to be slow (and a lot slower in the debugger!)

Accessing Sub functions /procedures from DPR or other function / procedure in Delphi

As much I know - Subroutines are with Private access mode to its parent unction / procedure, right?
Is there any way to access them from "outer-world" - dpr or other function / procedure in unit?
Also - which way takes more calcualtion and space to compiled file?
for example:
function blablabla(parameter : tparameter) : abcde;
procedure xyz(par_ : tpar_);
begin
// ...
end;
begin
// ...
end;
procedure albalbalb(param : tparam) : www;
begin
xyz(par_ : tpar_); // is there any way to make this function public / published to access it therefore enabling to call it this way?
end;
// all text is random.
// also, is there way to call it from DPR in this manner?
// in C++ this can be done by specifing access mode and/or using "Friend" class .. but in DELPHI?
Nested procedures/functions - those declared inside another procedure or function, are a special type, because they can access the stack (and thereby parameters/local variables) of the procedure they are nested in. Because of this, and Delphi scope rules, there is no way to access them outside the "parent" procedure. You use them only if you need to take advantage of their special features. AFAIK Delphi/Pascal is one of the few languages to have this feature. From a compiler point of view the call has some extra code to allow accessing the parent stack frame, IIRC.
AFAIK "friend" class/functions in C++ are different - they are class access methods, while in your example you are using plain procedures/functions.
In Delphi all procedure/classes declared in the same unit are automatically "friend", unless strict private declarations are used in latest Delphi releases. For example this code snippets will work, as long everything is in the same unit:
type
TExample = class
private
procedure HelloWorld;
public
...
end;
implementation
function DoSomething(AExample: TExample);
begin
// Calling a private method here works
AExample.HelloWordl;
end;
Note: Embedded Routines <> Private/Protected Methods.
Embedded routines i.e. routines inside routines can not be accessed by external routines.
You have posted an example of an Embedded routine, I also heard them called Internal Routines.
Here is another example:
procedure DoThis;
function DoThat : Boolean;
begin
// This Routine is embedded or internal routine.
end;
begin
// DoThat() can only be accessed from here no other place.
end;
Regardless of visibility, methods on classes, can be called using Delphi 2010 via RTTI. I have detailed how to do this in this article.
If you are in the same Unit methods on a class can be accessed by any other code regardless of visibility, unless they are marked with Strict Private. This Question has more details and good example code in the accepted answer.
If you are in two different units you can use the Protected Method Hack to access the protected methods. Which is detailed in detailed in this article.
Yes, you can access a subroutine, which is nested in other (parent) subroutine, from the outer world. Though it's somewhat tricky. I've found this howto in the web.
How to pass nested routine as a procedural parameter (32 bit)
Delphi normally does not support passing nested routines as procedural parameters:
// This code does not compile:
procedure testpass(p: tprocedure);
begin
p;
end;
procedure calltestpass;
procedure inner;
begin
showmessage('hello');
end;
begin
testpass(inner);
end;
The obvious workaround is to pass procedure address and typecast it within testpass:
// This code compiles and runs OK
procedure testpass(p: pointer);
begin
tProcedure(p);
end;
procedure calltestpass;
procedure inner;
begin
showmessage('hello');
end;
begin
testpass(#inner);
end;
There is, however, a pitfall in the above example - if the "inner" routine references any variable that was pushed onto the stack before the "inner" procedure was called from testpass (calltestpass parameters - if there were any, or local variables in calltestpass - if there were any), your system most probably crashes:
// This code compiles OK but generates runtime exception (could even be
// EMachineHangs :-) )
procedure testpass(p: pointer);
begin
tProcedure(p);
end;
procedure calltestpass;
var msg: string;
procedure inner;
begin
msg := 'hello';
showmessage(msg);
end;
begin
testpass(#inner);
end;
The reason is, in simple words, that the stack frame arrangement
was "broken" by the call to testpass routine and "inner" procedure
incorrectly calculates parameters and local variables location
(do not blame Delphi, please).
The workaround is to set up the correct stack context before
"inner" is called from within "testpass".
// This code compiles and runs OK
{$O-}
procedure testpass(p: pointer);
var callersBP: longint;
begin
asm // get caller's base pointer value at the very beginning
push dword ptr [ebp]
pop callersBP
end;
// here we can have some other OP code
asm // pushes caller's base pointer value onto stack and calls tProcedure(p)
push CallersBP
Call p
Pop CallersBP
end;
// here we can have some other OP code
end;
{$O+}
procedure calltestpass;
var msg: string;
procedure inner;
begin
msg := 'hello';
showmessage(msg);
end;
begin
testpass(#inner);
end;
Please note the optimization is switched OFF for testpass routine - optimization generally does not handle mixed OP/assembler code very well.
No, there is no way to do what you're asking. The xyz function is callable only by the enclosing blablabla function. Outside that function, xyz is not in scope and there is no way to name it. If C++ allowed nested function, there wouldn't be any way to refer to it, either, just like there's no way to refer to functions with static linkage from outside the current translation unit.
If you need to call xyz from outside the blablabla function, then move xyz outside. If you need to call it from outside the current unit, then you need to declare that function in the unit's interface section. Then, add that unit to the external code's uses clause and you can call xyz from wherever you want, even the DPR file.
If xyz refers to variables or parameters of the blablabla function, then you'll need to pass them in as parameters since xyz will no longer have access to them otherwise.
The concept of access specifiers isn't really relevant here since we're not talking about classes. Units have interface and implementation sections, which aren't really the same as public and private sections of a class.

Resources