Solved

Call a C++ DLL from Delphi

Posted on 1997-05-13
6
704 Views
Last Modified: 2010-04-04
Hi,
I'm working with Delphi(2.0) and right now I'm stuck in a very stupid problem. The problem deals with the loading of a DLL. This DLL is built with Microsoft C++ 1.52.

It is impossible to load this DLL and I tried it in two ways:

1) First, (Proof #1 below) is the implicit way and when I
   execute it from the Delphi environment the returned is:
   "Debugger Kernel Error. Error Code: 1."

2) Second, (Proof #2) is the explicit way. When I execute
   the routine "LoadLibrary(...)" it returns always zero.
   This error means:
   "System was out of memory, executable file was corrupt,
   or relocations were invalid". (?!?)

For your information, the DLL in question (TEKDCI.DLL) contains some functions to control an image acquisition board.

I will be very grateful if you could help me in this trouble. Thank you in advance and don't hesitate to contact me for further information or anything else.

Sincerely yours,

Jesus Galceran

------------------------------------------------------------
   Proof #1 (Implicit Load)
------------------------------------------------------------

   unit Init2;

   interface

   uses
     Windows, Messages, SysUtils, Classes, Graphics,
     Controls, Forms, Dialogs, StdCtrls, Buttons;

   type
     TForm1 = class(TForm)
       Button1: TButton;
       procedure Button1Click(Sender: TObject);
     private
       { Private declarations }
     public
       { Public declarations }
     end;

   var
     Form1: TForm1;
     BoardID : Integer;

   implementation

   {$R *.DFM}

   function TEK_Init: Integer; far pascal; external
   'TEKDCI.DLL';


   //
   //  Loading & Calling the DLL
   //
   procedure TForm1.Button1Click(Sender: TObject);
   begin
      BoardID:=TEK_Init;
      if BoardID > 0 then ShowMessage ('Board Initialized')
      else ShowMessage ('Initialization Failure');
   end;

   end.




------------------------------------------------------------
   Proof #2 (Explicit Load)
------------------------------------------------------------

   unit Init3;

   interface

   uses
     Windows, Messages, SysUtils, Classes, Graphics,
     Controls, Forms, Dialogs, StdCtrls, Buttons;


   type
     TInit = function: Integer;

     TForm1 = class(TForm)
       Button1: TButton;
       procedure Button1Click(Sender: TObject);
     private
       { Private declarations }
     public
       { Public declarations }
     end;

   var
     Form1  : TForm1;
     hTekDCI: THandle;
     Init   : TInit;
     FuncPtr: TFarProc;
     hDLL   : THandle;
     BoardID: Integer;

   implementation

   {$R *.DFM}

   //
   //  Loading & Calling the DLL
   //
   procedure TForm1.Button1Click(Sender: TObject);
   begin
      hTekDCI:=LoadLibrary('tekdci.DLL');
      if hTekDCI < HINSTANCE_ERROR then  
      begin
         ShowMessage ('      Error loading DLL      ');
         exit;
      end
      else begin
         FuncPtr:=GetProcAddress(hTekDCI, 'TEK_Init');
         @Init:=FuncPtr;
         if @Init <> nil then
         begin
            BoardID:=Init;
            if BoardID > 0 then ShowMessage ('Board Init')
            else ShowMessage ('Initialization Failure');
         end
         else ShowMessage ('Can not Load Routine');
      end;
      FuncPtr:=nil;
      FreeLibrary(hTekDCI);
   end;

   end.




------------------------------------------------------------
   Notes PERHAPS important:
------------------------------------------------------------

- In file DLL.H (included by the manufacturer) there is the   following definition:
     #define DLLCALL  __far __pascal __export

- Next, there is the TEK_Init() definition

    int DLLCALL TEK_Init()

    * Parameters:
      -------------
         None

    * Return Value:
      -------------
         The function returns <0 to indicate failure. If
         initialization is successful it returns the Board
         ID. The return ID can be 0, 1 or 2.

         Error Code Definition: 1: No hardware installed
                                2: Fail to initial hardware
                                3: INI file not found
                                4: DMA vxd not installed
                                5: No DCI Driver
                                6: Create DCI Primary Fail
                                7: Lock Memory Error

    * Description:
      -------------
         This function initializes the board using the               information specified in the INI file.

0
Comment
Question by:galceran
  • 3
  • 2
6 Comments
 
LVL 3

Expert Comment

by:sperling
ID: 1336204
The problem is simply that the DLL is 16-bit...

You need to use thunking to make this work, or you need to write the app in Delphi 1.

If you need help with thunking, leave me a comment and I'll look into it.

Regards,

Erik.
0
 
LVL 3

Accepted Solution

by:
mheacock earned 25 total points
ID: 1336205
Exactly...32 bit to 16 bit not possible without a thunking
layer.  I've written some thunking.  I could forward you
a good article from the Delphi Magazine and some example code
of mine.

Just include your e-mail address.
0
 
LVL 3

Expert Comment

by:mheacock
ID: 1336206
The only problem is that this thunking makes use of an
undocumented function in Kernel32 call QT_Thunk.  Since it
is undocumented, there is no guarantee that Microsoft will
keep the function in future Windows versions.  It will also
not work in Windows NT.  As I understand it, no 32-bit app
can thunk to a 16-bit DLL in WinNT.

But QT_Thunk is really the only method to thunk in Delphi
down to 16 bits.  The other methods work mainly with C/C++
(the MS version)...to get those methods to work with Delphi
(from what I hear) is so much trouble as not to be worth it.

Anyhow, I've done it with QT_Thunk and it works pretty good.
0
Active Directory Webinar

We all know we need to protect and secure our privileges, but where to start? Join Experts Exchange and ManageEngine on Tuesday, April 11, 2017 10:00 AM PDT to learn how to track and secure privileged users in Active Directory.

 
LVL 3

Expert Comment

by:mheacock
ID: 1336207
Your other option would be to contact the makers of the DLL
and see if they have a 32 bit version...or if you have the
source code...it shouldn't be too difficult to recompile as
32 bit.
0
 

Author Comment

by:galceran
ID: 1336208
I'm interested in the mentioned Delphi Magazine article.
My e-mail address is galceran@esaii.upc.es

Thanks in advance
0
 

Author Comment

by:galceran
ID: 1336209
I'm interested in the mentioned Delphi Magazine article.
My e-mail address is galceran@esaii.upc.es

Thanks in advance
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

Suggested Solutions

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…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Two types of users will appreciate AOMEI Backupper Pro: 1 - Those with PCIe drives (and haven't found cloning software that works on them). 2 - Those who want a fast clone of their boot drive (no re-boots needed) and it can clone your drive wh…

832 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