Solved

DLLs

Posted on 1997-03-24
1
419 Views
Last Modified: 2010-04-04
I just got a great answer about a Dll question.
So Heres another one .
if I have 2 dll's both have the same function names
when I load the dll's as so :

Hinst := LoadLibrary('c:\files\mikes\projects\dll\project1.dll');
if Hinst > 32 then;
   begin
    FPointer := GetProcAddress(Hinst, 'EntryPoint');
      if FPointer <> Nil then
        begin
          MyProc := proc(FPointer);
          try
            MyProc(MainMenu1);;
          except
           FreeLibrary(HInst);
           ShowMessage('Error in Calling EntryPoint in DLL');
          end;
       end;
     end;

Hinst := LoadLibrary('c:\files\mikes\projects\dll\DLL2.dll');
if Hinst > 32 then;
   begin
    FPointer := GetProcAddress(Hinst, 'EntryPoint');
      if FPointer<> Nil then
        begin
          MyProc := proc(FPointer);
          try
            MyProc(MainMenu1);
          except
           FreeLibrary(HInst1);
           ShowMessage('Error in Calling EntryPoint in DLL');
          end;
       end;


     end;
what the dlls do are they loads two menu Items. This works the two deffernt menu  do load but when I click on the first menu item(first dll that loaded) it runs the right function. when I click on the 2nd menu item(the 2nd dll that loaded) it runs the first menu item not the 2nd?

Both dll have the same function names but the function do differnt things. can anyone explain this to be because I thought if the dlls load in there own memory space the function address would be differnt even if they were name the same. well I quest I'm wrong?

--------------- Code for Dll --------------------------------------
//both dlls are the same except for the showmessage()
//which is in the  DynaClick() procedure.
uses
  Menus, Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

type
  TEvent = procedure(Sender: TObject) of object;
  TSomeClass = Class
  procedure DynaClick(Sender: TObject);
end;

 var
  NewMenu : TMenuItem;
  SomeClass : TSomeClass;
  Event : TEvent;

procedure TSomeClass.DynaClick(Sender: TObject);
begin
  showMessage('Its Dll 2');
end;

procedure EntryPoint(AMenu: TMenu); export; stdcall;
var
  NoItem  : TMenuItem;
begin
   //create a event handler...
  SomeClass := TSomeClass.Create;
   //assign Event to DynaClick to be pass to the menu Onclick event...
 Event := SomeClass.DynaClick;

 NoItem := AMenu.Items[AMenu.Items.Count - 1];
 NewMenu := TMenuItem.Create(NoItem);
 NewMenu.Caption := 'DLL2 Menu';
 NewMenu.OnClick := Event;
 NoItem.Insert(NoItem.Count, NewMenu);
 SomeClass.Free;
end;

exports
   EntryPoint;

0
Comment
Question by:mikec459
1 Comment
 
LVL 3

Accepted Solution

by:
sperling earned 100 total points
ID: 1334940
Hmmm... Start with removing the SomeClass.Free from your EntryPoint function. That won't help, but the menuitems OnCLick will call a method of a destroyed object.

Everytime you, or VCL code, calls TMenuItem.Create, a new unique word is reserved as the "Command ID" of the menu item. This "Command ID" is passed on to Windows, and when you click an item, windows passes the command ID back to the VCL, which then again uses this ID to determine what TMenuItem.OnCLick it should call.
The problem is that the method the VCL uses to allocate these unique IDs are local to the application and the DLLs. This means that when you call TMenuItem.Create in the first DLL the menu item will allocate the first unique command ID within the DLL. And so will DLL 2, meaning you get two menu items with the same ID.

Try redesigning a bit:

Have your DLL export a function, "MenuItemClicked" or something.
Declared like this:
  procedure MenuItemClicked; export; stdcall;

Create the menuitem in the app, and pass the item to EntryPoint.

EntryPoint should set the caption, help context and so on of the TMenuItem. In addition, include this line:

  AMenuItem.Tag := INTEGER(@MenuItemClicked);


The application should set the OnClick event for all created menu items to a common procedure, e.g. DLLMenuItemClicked.

procedure TForm1.DLLMenuItemClicked(Sender : TObject);
type
  TClickProc = procedure; stdcall;
var
  ClickProc : TClickProc;
begin
  @ClickProc := POINTER(TMenuItem(Sender).Tag);
  ClickProc;
end;


This scheme should work, although I haven't tested it. Leave me a comment if you get trouble...
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…

685 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