Solved

Multiple Concurrent DLLs

Posted on 2004-09-11
9
241 Views
Last Modified: 2010-04-05
I have a DLL which is called from an Office productivity app.   However, the initialisation data (provided by the caller) is unique to that instance.   This initial data is subsequently used for correct functioning of the DLL ....   At present it all works fine when I have just a single instance of the app & DLL active, but I want to progress to multiple documents ...

My question is, how do I handle multiple instances ?   I can have multiple instances of the app, and/or multiple document instances.   Can I tell the DLL to create a new instance each time (its not that big, so memory is not an issue), or should I create a new data structure for each instance with the unique data stored therein, or is there some other way ?

I would imagine this is a fairly common thing with MDI applications these days, but would like a 'heads up' before I start so I can go directly for the best solution.

Does anyone have any code snippets on this (preferably Delphi, but could convert VB or C code is necessary) ?   All help, references etc appreciated.

Thanks
Geoff
0
Comment
Question by:geoffdb
9 Comments
 
LVL 2

Expert Comment

by:gary_williams
ID: 12033811
Am I correct in assuming that your DLL is an "old style" DLL, i.e., not an ActiveX library?
0
 

Author Comment

by:geoffdb
ID: 12037619
Yes, correct.   In fact, its actually an XLL (a compiled equivalent of an Excel add-in), which is in effect a DLL with some additional special functions.

Geoff
0
 
LVL 33

Accepted Solution

by:
Slick812 earned 250 total points
ID: 12041069
?????????
I really do not understand your request?
As I have used librarys, the Program that loads a DLL, has that DLL as a "Part" of it's  program's memory space. . . and if you start another instance of that same program, and load that same DLL, the two loaded DLL's will NOT have any connection to each other , variables are not shared and the two programs do not share any memory, and their DLL's do NOT share any memory (in Delphi, although in C++ you can specify some shared variable memory, and in Delphi you can have a Memory Mapped File  to share data), , ,.
And if you have a MDI, the DLL is NOT loaded more than once, no matter how many times you call LoadLibrary( ), so in a MDI you will need to have methods to have separate DATA for each Document. . . .
so you will need to have a separate DLL function for the "initialisation data" for each Document, and then keep an Array of Document Data, or other Data storage for each document. . .
maybe more information about your MDI problems would help you get a solution?
0
 
LVL 17

Expert Comment

by:Wim ten Brink
ID: 12044775
You can only load a DLL once per application. Not multiple times. Thus you can't create multiple instances of the DLL. But of whatever you do inside your DLL is up to you. You control if the objects in the DLL can be created only once or multiple times.

I'd advise to use a global variable to use for the DLL handle when you load it. Then you can share the DLL handle within all other parts of your application.
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 

Author Comment

by:geoffdb
ID: 12062034
Alex & Slick812

Thanks for both your answers.   I understand better now.   I was hoping for some way to easily load a new DLL each time a new document was created (in the MDI instance), but it sounds like that is not possible.

Do you have, (or are able to point me to), some sample code of a simple example on this ?

Thanks
Geoff
0
 
LVL 33

Assisted Solution

by:Slick812
Slick812 earned 250 total points
ID: 12080709
Example of WHAT?, can not see what you want? I guess you can do a DLL, since you say you have one that works? ? So I guess you want some, I do not know? Store Data in DLL I GUESS? ? ?

OK some code, but this is a just one way of Thousands to store Data, Here is a Library Code that has 3 export functions -

function AddToStorage(pName: PChar; Int1, Int2: Integer): Integer;
  // this will add a storage Item and set three datas to Item

function GetStorage(Index: Integer; out pName: PChar;
                    out Int1, Int2: Integer): Bool; export;
  // this will Get three datas from storage Item Index

function DeleteStorage(Index: Integer): Bool;
  // this will Delete a Storage Item

I use a TList in the DLL for the Storage, a TList has several methods for Item addition and changes, you should look at the Delphi Help for "TList" if you need any more methods in your DLL.

code for library - - -


library demoDLL;

uses
  SysUtils, Classes,
  Windows, Messages;


type
  PInfo = ^TInfo;
  TInfo = record
    Name: String;
    Int1, Int2: Integer;
    end;


var
Storage: TList;


// do NOT use Strings in a export DLL function
function AddToStorage(pName: PChar; Int1, Int2: Integer): Integer; export;
var
pInfo1: PInfo;
begin
// adds a new Item to Storage and returns it's index, or -1 for ERROR
Result := -1;
New(pInfo1);
pInfo1.Name := pName;
pInfo1.Int1 := Int1;
pInfo1.Int2 := Int2;
try  // not to have exception in DLL is beter, just return an ERROR result for function
  Storage.Add(pInfo1);
  except
  Exit;
  end;
Result := Storage.Count-1;
end;


function GetStorage(Index: Integer; out pName: PChar;
                    out Int1, Int2: Integer): Bool; export;
var
pInfo1: PInfo;
begin
// retrives Info data from Storage Item Index
Result := False;
pName := nil;
if (Index < 0) or (Index > Storage.Count-1) then Exit;

try
pInfo1 := Storage.Items[Index];
  except
  Exit;
  end;
pName := PChar(pInfo1.Name);
Int1 := pInfo1.Int1;
Int2 := pInfo1.Int2;
Result := True;
end;

function DeleteStorage(Index: Integer): Bool; export;
begin
// deletes an Index Item from storage
Result := False;
if (Index < 0) or (Index > Storage.Count-1) then Exit;
try
  Dispose(Storage.Items[Index]);
  Storage.Delete(Index);
  except
  Exit;
  end;
Result := True;
end;


procedure AttatchProc(cReason: Cardinal);
var
i: Integer;
begin
if (cReason = Dll_Process_Detach) then
 begin
 for i := 0 to Storage.Count -1 do
   Dispose(Storage.Items[i]);
 FreeAndNil(Storage);
 end;
end;

exports
  AddToStorage,
  GetStorage,
  DeleteStorage;


begin
DLLProc := @AttatchProc;
Storage := TList.Create;
end.


 = = = = = = = = =  = = =  = = = = = = = = =  = = = =

code for button Click in program to use DLL - - - -



procedure TForm1.sbut_DoStorageDLLClick(Sender: TObject);
var
hLibS: THandle;
AddToStorage: function(pName: PChar; Int1, Int2: Integer): Integer;
GetStorage: function(Index: Integer; out pName: PChar;
                    out Int1, Int2: Integer): Bool;
DeleteStorage: function(Index: Integer): Bool;

Int1, Int2, Index: Integer;
Name: String;
pName: PChar;

begin
// button Click
hLibS := LoadLibrary('demoDLL.dll');
if hLibS = 0 then
  begin
  ShowMessage('Did not load the DLL');
  Exit;
  end;

@AddToStorage := GetProcAddress(hLibS, 'AddToStorage');
if @AddToStorage = nil then
  begin
  ShowMessage('AddToStorage is nil');
  FreeLibrary(hLibS);
  Exit;
  end;

Name := 'John Programmer';
Int1 := 111;
Int2 := 222;

{when you create a NEW Document, you can store Info for that Document
with AddToStorage}
Index := AddToStorage(PChar(Name), Int1, Int2);
if Index > -1 then
  ShowMessage('AddToStorage Worked, Index is '+IntToStr(Index))
  else
  ShowMessage('ERROR - AddToStorage   FAILED');

Name := 'SomeOne Else Jr';
Int1 := 333;
Int2 := 444;

Index := AddToStorage(PChar(Name), Int1, Int2);
if Index > -1 then
  ShowMessage('AddToStorage Worked, Index is '+IntToStr(Index))
  else
  ShowMessage('ERROR - AddToStorage   FAILED');

{getStorage will get Data from Index Item}
@GetStorage := GetProcAddress(hLibS, 'GetStorage');
if @GetStorage = nil then
  begin
  ShowMessage('GetStorage is nil');
  FreeLibrary(hLibS);
  Exit;
  end;

if GetStorage(0, pName, Int1, Int2) then
  begin
  Name := pName;
  ShowMessage('GetStorage Worked,'#10'Int1 = '+IntToStr(Int1)+' Int2 = '+
               IntToStr(Int2)+' '+Name);
  end else
  ShowMessage('ERROR - GetStorage   FAILED');

FreeLibrary(hLibS);
end;

 - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - -

but I was just guessing,
0
 

Author Comment

by:geoffdb
ID: 12082295
Slick812

That's great thanks, let me give it a whirl !!

Geoff
0
 

Author Comment

by:geoffdb
ID: 12099999
Slick812

I gave this a whirl today -it works a treat !!   Thanks.

I'm going to up the points for your good response, but have a couple of questions :

a) AttatchProc : Can you explain this to me please, and how it works, and where the cReason argument comes from - is this an automatic DLL argument ?      The function reference appears to be called only when the DLL is created, is it an implicit thing that it is called again on destroy with the DLL_Process_Detach argument ?

Alternatively, can one use create and destroy methods for the same thing ?

and secondly
b) Debugging DLLs : How do I interactively debug a DLL ?  
I was going to debug this to see how/where the AttatchProc func was called - then instantly realised that as it's a DLL can't do that with the IDE .. My experience is really only with executables, so using the IDE with them is fine ... my experience with DLLs is fairly new, have just used debug ShowMessage and/or wrteln type statements so far, but understand it is possible to debug interactively.

I'm using Delphi 6 BTW, though have 7 & 8 also.

Many thanks
Geoff
0
 
LVL 33

Expert Comment

by:Slick812
ID: 12106634
you should look in the Delphi help for "DLLProc" and it says -

   DLLProc is used to specify a procedure that is invoked every time a DLL's entry point is called, so on thread and process detatch it is called, , , Although in delphi this is not entirely accurate, you will need to ecplictly call your DLLProc with the  "DLL_PROCESS_ATTACH"  parameter to get that functioning, so that DLL_PROCESS_ATTACH is almost a usless kind of thing, you can just do any initialization code between the begin and end or call the DLLProc if you would rather - -



procedure AttatchProc(cReason: Cardinal);
var
i: Integer;
begin
if (cReason = DLL_PROCESS_ATTACH) then
  Storage := TList.Create;

if (cReason = Dll_Process_Detach) then
 begin
 for i := 0 to Storage.Count -1 do
   Dispose(Storage.Items[i]);
 FreeAndNil(Storage);
 end;
end;


begin
DLLProc := @AttatchProc;
AttatchProc(DLL_PROCESS_ATTACH);

end.


- - - - - - - - - - -  - - - - -  - - - - - - -  --

I do not usually Debug a DLL, except with a messageBox or some file write, however, as I understand it you can assign a program to run when you press the green "Run" arrow, and the program can run in the Debugger, allowing you to catch code misconduct, , but I have forgotten the steps needed to set a program to run, I guess it's in the delphi help
0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

Suggested Solutions

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now