Solved

DLLs

Posted on 1997-03-24
1
400 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

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

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

705 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

14 Experts available now in Live!

Get 1:1 Help Now