Solved

DLLs

Posted on 1997-03-24
1
416 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: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

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

Suggested Solutions

Title # Comments Views Activity
URL for downloading Google Chrome for Win XP 2 182
Delphi 2 69
Base1 Encode/Decode 3 81
DBCtrlGrid, Delphi, Scroll 8 37
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…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Although Jacob Bernoulli (1654-1705) has been credited as the creator of "Binomial Distribution Table", Gottfried Leibniz (1646-1716) did his dissertation on the subject in 1666; Leibniz you may recall is the co-inventor of "Calculus" and beat Isaac…
In a recent question (https://www.experts-exchange.com/questions/29004105/Run-AutoHotkey-script-directly-from-Notepad.html) here at Experts Exchange, a member asked how to run an AutoHotkey script (.AHK) directly from Notepad++ (aka NPP). This video…

809 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