Board index » delphi » Call DLL using Dephi

Call DLL using Dephi

Dear all:

I have a DLL file names nirtd.dll written by VC. It contained serveral
functions like:

NIrtd_allocatevalue()
-> This function allocations string space within a value structure.
NIrtd_allocatevalue(NIrtd_stValue*value);
----------------------------------------------------------------------
 Parameter            Description
----------------------------------------------------------------------
 *value               Pointer to an already allocated value structure.
?@?@?@?@?@?@?@?@?@?@?@This function call allocates the string pointer
?@?@?@?@?@?@?@?@?@?@?@within the structure.
----------------------------------------------------------------------
 Return Code          Description
----------------------------------------------------------------------
 NIrtd_eOK            Operation successful.
 NIrtd_eALLOC_FAILED  Allocation of memory not successful

NIrtd_freevalue()
-> This function frees string space within a value structure.
void NIrtd_freevalue(NIrtd_stValue*value);
----------------------------------------------------------------------
 Parameter            Description
----------------------------------------------------------------------
 *value               Pointer to a value that has been fully allocated
?@?@?@?@?@?@?@?@?@?@?@by a previous call to NIrtd_allocatevalue. This
?@?@?@?@?@?@?@?@?@?@?@function call frees the string pointer within
?@?@?@?@?@?@?@?@?@?@?@the structure.

I also have related .h and .lib files. Is it possible to call these
functions using Delphi5? It's a big question. Thanks for help.

                                                             hagar.

 

Re:Call DLL using Dephi


Quote
On Sat, 24 Mar 2001 12:29:23 +0800, "hagar" <ha...@gcn.net.tw> wrote:
>Dear all:

>I have a DLL file names nirtd.dll written by VC. It contained serveral
>functions like:

<snips>

Quote
>I also have related .h and .lib files. Is it possible to call these
>functions using Delphi5? It's a big question. Thanks for help.

From the look of the items you sent it will probably work, you'll need
to translate the .H file into a Delphi import unit for the types and
exported routine calls.  The .lib file won't be needed as that's
presumably compiled into the .DLL and Delphi can access exported .DLL
routines directly (and doesn't know what to do with .lib files
anyway).

If you've never done a translation like that before it can be
relatively simple, quite a challenge, or all the way to impossible
depending on how the C/C++ code was written (and your famiiiarity with
C/C++ and Delphi).

There are a couple of utilities available on the Net that can perform
some of the more knee-jerk aspects of the translation for you; but
the result still has to be gone over in some detail to make sure
everything makes sense Pascal-wise (if it even compiles to start with,
which is unlikely).

How large is the .H file?

Stephen Posey
slpo...@concentric.net

Re:Call DLL using Dephi


Quote
hagar <ha...@gcn.net.tw> wrote in message

news:99h7r0$1nl@netnews.hinet.net...
Quote
> Dear all:

> I have a DLL file names nirtd.dll written by VC. > I also have related .h

and .lib files. Is it possible to call these

Quote
> functions using Delphi5? It's a big question. Thanks for help.

the answer is yes. you'll need to add the function prototype to your app and
then link the dll in using the external directive. the delph help entry
"Calling DLLs" explains the process pretty clearly.

--
A closed mouth gathers no flies.

ICQ: 91418899
http://www.planeted.co.uk
http://members.nbci.com/edduffe

Re:Call DLL using Dephi


This is straight forward provided you get three things right.

a) translate the function parameters correctly.
b) get the calling convention right
c) understand that the function names output by the VC compiler will most
likely be decorated.

The answer to all these issues should be in the .h file.

Point a):
The only parameter it seems you have to deal with is a pointer to type
NIrtd_stValue. This makes life easy, as you can translate the functions as
follows..

function NIrtd_allocatevalue(var value: TNIrtd_stValue): TReturnType; cdecl;
external  'myDLL';
procedure NIrtd_freevalue(var value: NIrtd_stValue); cedecl; external
'myDLL';

Now the problem changes to one of declaring TNIrtd_stValue correctly. The
main trap in dealing with structures, is that packing conventions differ
between C and Pascal. The answer to this may be in the header file, placed
before the structure definition in the form of a packing #pragma directive,
but the chances are not, and you will have to know the default packing
behaviour of the compiler. If you can't match the structure to a Delphi
record, you will have to allocate a block of memory for the function to
write back to, and extract what you need out of that into a suitable record.

You will also need to have the enum definition for NIrtd_eOK,
NIrtd_eALLOC_FAILED. This should be in the header.

Point b)
 I've used the cdecl calling convention in the example above, but it may be
stdcall or something else. Look for the export declaration in the header.

Point c)
C++ compilers decorate the function name. What this means for you, is that
the function won't be called NIrtd_allocatevalue in the actual DLL, but
something like it with a whole heap of apparent gibberish (obviously its
anything but!) added on. Thus when you Delphi executable runs, it will fail
to find the function name in the DLL. The answer once again should be in the
header file. If the export declaration is bracketed by the # extern C
directive, then C linkage is turned on, and name decoration suppressed.

If you are stuck with the decorated function names, you can view the DLL
with QuickView, get hold of the actual name being used (it will be mangled
but recognizable) and use that in your procedure declaration as follows...

procedure NIrtd_freevalue(var value: NIrtd_stValue); cedecl; external
'myDLL' name 'NIrtd_freevalue@1213##';

Dave

Quote
hagar <ha...@gcn.net.tw> wrote in message

news:99h7r0$1nl@netnews.hinet.net...
Quote
> Dear all:

> I have a DLL file names nirtd.dll written by VC. It contained serveral
> functions like:

> NIrtd_allocatevalue()
> -> This function allocations string space within a value structure.
> NIrtd_allocatevalue(NIrtd_stValue*value);
> ----------------------------------------------------------------------
>  Parameter            Description
> ----------------------------------------------------------------------
>  *value               Pointer to an already allocated value structure.
> ?@?@?@?@?@?@?@?@?@?@?@This function call allocates the string pointer
> ?@?@?@?@?@?@?@?@?@?@?@within the structure.
> ----------------------------------------------------------------------
>  Return Code          Description
> ----------------------------------------------------------------------
>  NIrtd_eOK            Operation successful.
>  NIrtd_eALLOC_FAILED  Allocation of memory not successful

> NIrtd_freevalue()
> -> This function frees string space within a value structure.
> void NIrtd_freevalue(NIrtd_stValue*value);
> ----------------------------------------------------------------------
>  Parameter            Description
> ----------------------------------------------------------------------
>  *value               Pointer to a value that has been fully allocated
> ?@?@?@?@?@?@?@?@?@?@?@by a previous call to NIrtd_allocatevalue. This
> ?@?@?@?@?@?@?@?@?@?@?@function call frees the string pointer within
> ?@?@?@?@?@?@?@?@?@?@?@the structure.

> I also have related .h and .lib files. Is it possible to call these
> functions using Delphi5? It's a big question. Thanks for help.

>                                                              hagar.

Re:Call DLL using Dephi


Thanks for all of you. I'm sorry that I'm not familiar of C or C++, so my
qruestions
are a lot and my be unclear. My questions are described below:
1. I download HeadConv written by Bob Swart to convert nirtdapi.h to
nirtdapi.pas,
?@nirtdtyp.h to nirtdtyp.pas. Should I add these pas files(unit) after uses
clause?
2. I'm confused with data types to translate the function parameters
correctly. David
?@had given an example, I'll try it.
3. Now I list the content of the .pas files converted by HeadConv below. Is
there any
?@errors in it? And also I list the .h files. Finally, Thanks for help. So
many thanks.

------ nirtdapi.pas ------

unit NIRTDAPI;
{**************************************************************************}
{                                                                          }
{    This C DLL header file first (automatic) conversion generated by:     }
{    HeadConv 4.0 (c) 2000 by Bob Swart (aka Dr.Bob - www.drbob42.com)     }
{      Final Delphi-Jedi (Darth) command-line units edition                }
{                                                                          }
{    Generated Date:  2001/3/26                                            }
{    Generated Time: AM
         }
{                                                                          }
{**************************************************************************}

interface
uses
{$IFDEF WIN32}
  Windows;
{$ELSE}
  Wintypes, WinProcs;
{$ENDIF}

{=> e:\software\headconv\NIRTDAPI.H <=}

{$IFNDEF NIRTDAPI_H_HEADER && !defined(NO_CCMP_SCCS_ID)}
{$DEFINE NIRTDAPI_H_HEADER}
{ static char SCCS_ID_NIRTDAPI_H[] = "@(#) nisbuild 97/12/25 1:14:35
nirtdapi.h \\main\\1 ~"; }
{/// nisbuild 97/12/25 1:14:35 nirtdapi.h \main\1 ~ }
{/// }
{/// nisbuild 97/5/3 21:44:35 nirtdapi.h \\main\\r01\\1 ~ }
{/// [INITR01] Creating r01 version of file from mb7 branch }
{/// }
{/// lamki 97/4/9 11:40:15 nirtdapi.h \\main\\mb7\\3 ~ }
{/// [BV64308_MB7] : Add new columns and tables into NIrtd api dll }
{/// }
{/// howardt 97/2/6 11:16:28 nirtdapi.h \\main\\mb7\\2 ~ }
{/// [BV61983] A Fix. }
{/// }
{$ENDIF}

{+// }
{/// Copyright Notice: Copyright (c)1996 NorTel Corporation, All Right
Reserved }
{/// }
{/// @doc }
{/// }
{/// @module nirtdapi.h | Real Time Data Application Interface Header
File. }
{/// The following APIs are used to obtain real-time statistical data from
the }
{/// next generation call center product from NorTel. }
{///////////////////////////////////////////////////////////////////////////
//*/ }

{$IFNDEF _NIRTDAPI_H}
{$DEFINE _NIRTDAPI_H}

{$INCLUDE <nirtdtyp.h>}

{-/* }
{/// Prototypes for public functions. // }
{///////////////////////////////////////////////////////////////////////////
////*/ }
{$IFDEF __cplusplus}
{-extern "C" { }
{$ENDIF}

{=/* Called to allocate the query structure and install }
{+// that the table indicated is to be queried for.*/ }
var
  function NIrtd_allocateQuery(var query: NIRTD_TQUERY;
                                table: NIRTD_TTABLEID): NIRTD_EXPORT cdecl
{$IFDEF WIN32} stdcall {$ENDIF};

{+// Called to select the desired columns. Note: The first column*/ }
{+// indicated must be the key for the table.*/ }
var
  function NIrtd_selectColumn:(var query: NIRTD_TQUERY;
                               column: NIRTD_TCOLUMNID): NIRTD_EXPORT cdecl
{$IFDEF WIN32} stdcall {$ENDIF};

{+// Called to allocate the conjunction structure.*/ }
var
  function NIrtd_allocateConjunction(var conj: NIRTD_TCONJUNCTION):
NIRTD_EXPORT cdecl  {$IFDEF WIN32} stdcall {$ENDIF};

{+// "And"ing a series of conditions. Note: Only key columns are
supported*/ }
{+// in this release.*/ }
var
  function NIrtd_addCondition(var conj: NIRTD_TCONJUNCTION;
                               column: NIRTD_TCOLUMNID;
                               oper: NIRTD_TOPERATOR;
                               var value: NIRTD_STVALUE): NIRTD_EXPORT cdecl
{$IFDEF WIN32} stdcall {$ENDIF};

{+// "Or"ing a series of conjunctions.*/ }
var
  function NIrtd_addConjunction(var query: NIRTD_TQUERY;
                                 var conj: NIRTD_TCONJUNCTION): NIRTD_EXPORT
cdecl  {$IFDEF WIN32} stdcall {$ENDIF};

{+// When finished with the conjunction, it should be de-allocated.*/ }
var
  function NIrtd_freeConjunction(var conj: NIRTD_TCONJUNCTION): NIRTD_EXPORT
cdecl  {$IFDEF WIN32} stdcall {$ENDIF};

{+// When finished with the query, it should be de-allocated.*/ }
var
  function NIrtd_freeQuery(var query: NIRTD_TQUERY): NIRTD_EXPORT cdecl
{$IFDEF WIN32} stdcall {$ENDIF};

{+// When finished with a values table, it should be de-allocated.*/ }
var
  function NIrtd_freeTableGroup(var tableGroup: NIRTD_STTABLEGROUP):
NIRTD_EXPORT cdecl  {$IFDEF WIN32} stdcall {$ENDIF};

{+// When finished with a row of values, it should be de=allocated.*/ }
var
  function NIrtd_freeRow(var row: NIRTD_TROW): NIRTD_EXPORT cdecl  {$IFDEF
WIN32} stdcall {$ENDIF};

{+// Login to the desired server.*/ }
var
  function NIrtd_login(var authorization: NIRTD_TAPIAUTH;
                        var servname: TCHAR;
                        var userID: TCHAR;
                        var passWord: TCHAR): NIRTD_EXPORT cdecl  {$IFDEF
WIN32} stdcall {$ENDIF};

{+// Request for one time data propagation.*/ }
var
  function NIrtd_singleDataRequest(var tableGroup: NIRTD_STTABLEGROUP*;
                                    var authorization: NIRTD_TAPIAUTH;
                                    var query: NIRTD_TQUERY): NIRTD_EXPORT
cdecl  {$IFDEF WIN32} stdcall {$ENDIF};

{+// Obtain the desired row from the passed table.*/ }
{+// Note: NIrtd_allocateRow makes a reference into the table. The table*/ }
{+// must not be freed until after the row is freed.*/ }
var
  function NIrtd_allocateRow(var row: NIRTD_TROW;
                              var table: NIRTD_STTABLE;
                              index: ULONG): NIRTD_EXPORT cdecl  {$IFDEF
WIN32} stdcall {$ENDIF};

{+// Dynamically allocate string space for a value structure.*/ }
var
  function NIrtd_allocateValue(var value: NIRTD_STVALUE): NIRTD_EXPORT cdecl
{$IFDEF WIN32} stdcall {$ENDIF};

{+// Free string space for a value structure.*/ }
var
  function NIrtd_freeValue(var value: NIRTD_STVALUE) cdecl  {$IFDEF WIN32}
stdcall {$ENDIF};

{+// Copy a value record into another pre-allocated value record.*/ }
var
  function NIrtd_cpValue(var destvalue: NIRTD_STVALUE;
                          const srcvalue: PNIRTD_STVALUE): NIRTD_EXPORT
cdecl  {$IFDEF WIN32} stdcall {$ENDIF};

{+// Obtain the desired column from the passed row.*/ }
var
  function NIrtd_getCol(var value: NIRTD_STVALUE;
                         var row: NIRTD_TROW;
                         index: ULONG): NIRTD_EXPORT cdecl  {$IFDEF WIN32}
stdcall {$ENDIF};

{+// Register for periodic data propagation.*/ }
var
  function NIrtd_startDataStream(var authorization: NIRTD_TAPIAUTH;
                                  var query: NIRTD_TQUERY;
                                  updateRate: ULONG;
                                  callback: NIRTD_FUNCALLBACK;
                                  yourpointer: Pointer;
                                  var requestId: NIRTD_TREQUESTID):
NIRTD_EXPORT cdecl  {$IFDEF WIN32} stdcall {$ENDIF};

{+// De-register from periodic data propagation.*/ }
var
  function NIrtd_stopDataStream(var authorization: NIRTD_TAPIAUTH;
                                 requestId: NIRTD_TREQUESTID): NIRTD_EXPORT
cdecl  {$IFDEF WIN32} stdcall {$ENDIF};

{+// Logout of server and disposes of authorization structure.*/ }
var
  function NIrtd_logout(var authorization: NIRTD_TAPIAUTH): NIRTD_EXPORT
cdecl  {$IFDEF WIN32} stdcall {$ENDIF};

{+// Initialize the Name cache for the indicated data column*/ }
var
  function NIrtd_getNameCacheforDataColumn(var authorization:
NIRTD_TAPIAUTH;
                                            column: NIRTD_TCOLUMNID):
NIRTD_EXPORT cdecl  {$IFDEF WIN32} stdcall {$ENDIF};

{+// Dynamically allocate string space for a name structure.*/ }
var
  function NIrtd_allocateName(var name: NIRTD_STNAME): NIRTD_EXPORT cdecl
{$IFDEF WIN32} stdcall {$ENDIF};

{+// Free string space for a name structure.*/ }
var
  function NIrtd_freeName(var name: NIRTD_STNAME) cdecl  {$IFDEF WIN32}
stdcall {$ENDIF};

{+// Copy a name record into another pre-allocated name record.*/ }
var
  function NIrtd_cpName(var destname: NIRTD_STNAME;
                         const srcname: PNIRTD_STNAME): NIRTD_EXPORT cdecl
{$IFDEF WIN32} stdcall {$ENDIF};

{+// Convert the passed column Id, and agent/skillset/application value into
a name*/ }
var
  function NIrtd_getName(var authorization: NIRTD_TAPIAUTH;
                          column: NIRTD_TCOLUMNID;
                          var value: NIRTD_STVALUE;
                          var name: NIRTD_STNAME): NIRTD_EXPORT cdecl
{$IFDEF WIN32} stdcall {$ENDIF};

{+// Go directly to the server to convert the name and update the Name Cache
with the result*/ }
var
  function NIrtd_getFailedName(var authorization: NIRTD_TAPIAUTH;
                                column: NIRTD_TCOLUMNID;
                                var value: NIRTD_STVALUE;
                                var name: NIRTD_STNAME): NIRTD_EXPORT cdecl
{$IFDEF WIN32} stdcall {$ENDIF};

{+// Go directly to the server to convert the name to a value.*/ }
var
  function NIrtd_getValue(var authorization: NIRTD_TAPIAUTH;
                           var name: NIRTD_STNAME;
                           column: NIRTD_TCOLUMNID;
                           var value: NIRTD_STVALUE): NIRTD_EXPORT cdecl
{$IFDEF WIN32} stdcall {$ENDIF};

{+// Refresh the Name cache for all previous data columns*/ }
var
  function NIrtd_refreshNameCache(var authorization: NIRTD_TAPIAUTH):
NIRTD_EXPORT cdecl  {$IFDEF WIN32} stdcall {$ENDIF};

{+// Remove a column from the name cache.*/ }
var
  function NIrtd_removeNameCacheforDataColumn(var authorization:
NIRTD_TAPIAUTH;
                                               column: NIRTD_TCOLUMNID):
NIRTD_EXPORT cdecl  {$IFDEF WIN32} stdcall {$ENDIF};

{+// Change ...

read more »

Re:Call DLL using Dephi


Quote
In article <99ma49$...@netnews.hinet.net>, "hagar" <ha...@gcn.net.tw> writes:
>3. Now I list the content of the .pas files converted by HeadConv below. Is
>there any
>?@errors in it?

This carries a bug in Bob's program in which it allocates both cdecl and
stdcall as the keyword indicating calling convention after the function
definition - only one should be used

In general unless you know the particular call used by the DLL writer you have
to try both of them to see which works.

One test which turned up in my use of a "foreign" DLL, is to use cdecl and
trace the call in the Delphi de{*word*81} using F8 (step past). If the call returns
to the calling line from the DLL then you must change the calling convention to
stdcall. If it returns to the next line after the call then cdecl is OK.

Look up Delphi documentation on calling conventions to see a description of
what using the different keywords imply.

Alan Lloyd
alangll...@aol.com

Other Threads