Solved

How do I call Dll functions (Written in C)

Posted on 1998-10-26
13
233 Views
Last Modified: 2010-04-06
I would like to call functions from a .dll compiled in C.
I have the .dll itself and the .h file.
I understand I have to write my own .pas file that will include the interface to the .dll.
What shold be the format of the functions there?
How do I use callback functions in that .dll - specifically, how do I send a pointer of one of my (delphi) functions to that .dll?
0
Comment
Question by:tommyq
  • 4
  • 4
  • 3
  • +2
13 Comments
 
LVL 4

Expert Comment

by:erajoj
Comment Utility
Hi,
Usually, you would use stdcall, like:
  function ext(value: Integer): Integer; stdcall; external 'mydll.dll' name 'Extfunc';

A pointer to the above function is "@ext".

If you find this troublesome;
send us the .h-file and we will have a look.

/// John
0
 
LVL 4

Expert Comment

by:erajoj
Comment Utility
Hi,
Usually, you would use stdcall, like:
  function ext(value: Integer): Integer; stdcall; external 'mydll.dll' name 'Extfunc';

A pointer to the above function is "@ext".

If you find this troublesome;
send us the .h-file and we will have a look.

/// John
0
 
LVL 4

Expert Comment

by:erajoj
Comment Utility
Whooah! My first doublepost ever... ;-)

/// John
0
 

Author Comment

by:tommyq
Comment Utility
Thanks erajoj for the prompt reply.
Let me try and use your double experies in C and Delphi.

Here is the function declerations from the .h file
/*
 * Functions prototypes.
 */
V_NODE __declspec(dllexport) initHeart ( char *heart_fname );
int    __declspec(dllexport) traverseTree ( void *(* callback)( void *x, void *y ), V_NODE tree );
V_NODE __declspec(dllexport) getNextVertex ( V_NODE v, int new_x, int new_y );
void   __declspec(dllexport) getData ( double *V0p, double *total_distp, V_NODE *current_nodep );
void   __declspec(dllexport) destructHeart ( V_NODE *root );
int      __declspec(dllexport)      TestDll ();

VNode is a struct with doubles and pointers.
1. Is this the right way to export the functions?
2. Could you give me an exmple for an apropriate decleration of the function traversTree which recieves a pointer to a callback function?
3. what should be the pascal decleration of the function that is being sent to traverse tree?

Thanks,
Tommy
0
 

Expert Comment

by:DPedrelli
Comment Utility
interface
function FunctionName(Param1: type; Param2: type): type; stdcall;
implementation
function FunctionName; external; 'DLLName.dll'; name 'CallNameInDelphi';

You may have to check the calling convention but stdcall is standard in C functions.  After the name directive, replace CallNameInDelphi with the name you want to use to call the function in Delphi.
Hope this helps.
David.
0
 

Author Comment

by:tommyq
Comment Utility
DPedrelli, Sorry for the rejection. I need some more info.

For example, how would I send the C code pointers to my functions, pointers to strings (char * in C = Pchar in Delphi).
How should I store pointers I receive from the called C function?
0
How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

 
LVL 4

Expert Comment

by:BoRiS
Comment Utility
tommyq

As far as I know you need to use extern or a full function

       eg. of extern

       extern "C" {
       int _EXP MyFunc (int i)
       {
         return (i+10);
       }
       }

       or the function using cdelc

       function MyFunc(i: integer): integer; cdecl; far; external 'MYDLL' index 12;

       you can declare the functions with FAR PASCAL and then call the function in the        normal way.

       If there are problems, make sure that you declare the DLL functions with "_loadds".         Remember that, normally, a DLL function
       runs on the caller's DS, unless you specifically load the correct one.
Later
BoRiS
0
 
LVL 10

Accepted Solution

by:
Lischke earned 60 total points
Comment Utility
Hi Tommy,

if you always keep in mind that the calling convention in C and Delphi are different then the solution isn't hard to find:

1) function declarations in your interface unit
- V_NODE __declspec(dllexport) initHeart ( char *heart_fname );

   function InitHeart(heart_fname: PChar): V_NODE; cdecl;

- int    __declspec(dllexport) traverseTree ( void *(* callback)( void *x, void *y ), V_NODE tree );

    function traverseTree(Func: TTraverseCallback; Tree: V_Node): Integer; cdecl;

- V_NODE __declspec(dllexport) getNextVertex ( V_NODE v, int new_x, int new_y );
    function GetNextVertex(V: V_Node; New_X, New_Y: Integer): V_NODE; cdecl;

- void   __declspec(dllexport) getData ( double *V0p, double *total_distp, V_NODE *current_nodep );
   procedure GetData(var VOp, total_siatp, current_nodep: Double; cdecl;

- void   __declspec(dllexport) destructHeart ( V_NODE *root );
   procedure destructHeart(root: PV_NODE); cdecl;

- int __declspec(dllexport) TestDll ();
    function TestDLL: Integer; cdecl;

PV_NODE is, as you surely already know a pointer to a V_NODE. The pointers to the double values in GetData can also be PDouble (pointer to double) in case you don't want to use the var key word. But since these parameters seems to be used to pass data back the declaration I've given is appropriate.

2) Specifying implemenation:

const HeartDLL = 'Heart.DLL';

function InitHeart(heart_fname: PChar): V_NODE; cdecl; external HeartDLL;
function traverseTree(Func: TTraverseCallback; Tree: V_Node): Integer; cdecl; external HeartDLL;
function GetNextVertex(V: V_Node; New_X, New_Y: Integer): V_NODE; cdecl; external HeartDLL;
procedure GetData(var VOp, total_siatp, current_nodep: Double; cdecl; external HeartDLL;
procedure destructHeart(root: PV_NODE); cdecl; external HeartDLL;
function TestDLL: Integer; cdecl; external HeartDLL;

If you use exactly the same names in Delphi as they are declared in C (case sensitive!) then you don't need to specify the names again in the external clause.

3) Callback definition:
type TTraverseCallback = function(X,Y: Pointer): Pointer; cdecl;

4) callback implementation:

function TraverseCallback(X, Y: Pointer): Pointer;

begin
  // do something
  Result:=MyValue;
  // etc.
end;

Use then

traverseTree(TraverseCallback,TheNode);

to actually traverse the tree.

If you don't have the source for the DLL then you should expect that there also could be used the stdcall calling convention (as it is used in all system DLLs). If you encounter access violations then try stdcall instead of cdecl.

The memory for the value passed to InitHeard can simply be gotten by declaring a String variable and calling:

MyNode:=InitHeart(PChar(AName));

with

var AName : String;

Anymore questions? Just ask :-)

Ciao, Mike
0
 
LVL 10

Expert Comment

by:Lischke
Comment Utility
Ooops,

found some typos in the text (the input window here is horrible...).

to 4) the function must also be declared with cdecl

GetData needs a closing parenthesis before cdecl

Ciao, Mike
0
 

Author Comment

by:tommyq
Comment Utility
Mike,

Thanks for your ELABORATED answer. It is amazing how an expert can help when you are desperate.
I will check it out and let you know.

Thanks again,
Tommy
0
 

Author Comment

by:tommyq
Comment Utility
Mike,

Thanks.
It worked.
You are great.

Tommy
0
 
LVL 4

Expert Comment

by:erajoj
Comment Utility
Mike, impressive answer!
If we had an "achiever of the month" award, I would vote for you this month. :-)

/// John
0
 
LVL 10

Expert Comment

by:Lischke
Comment Utility
;-)
0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Help to pass a value through a function 2 64
Delphi with SQL Natvie Client 15 73
Delphi OLE Error 8 82
Printing problem 2 72
Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
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…
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

763 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

13 Experts available now in Live!

Get 1:1 Help Now