converting C header to delphi; callback function definition in delphi

Posted on 2006-06-27
Medium Priority
Last Modified: 2010-04-05
Dear Experts!

I have a C DLL that I call from my delphi project. So far, so nice. I used dr.bob's headconv to get the header file converted to a delphi pas but needed to change some things manually to get the main functions in this DLL to work from my delphi project.

Now I run into 2 problems that I can't resolve by now.

At the beginning of the header file I have this define block, that is not correctly converted to the pas by headconv - bds2006 just says its unkown:

#define LIBNAME_API __declspec(dllexport)
#define LIBNAME_API __declspec(dllimport)

Where LIBNAME_API is used in this way in the C header:

LIBNAME_API int _stdcall call_libname_conv(char *inbuf, int inlen, char *outbuf, int outlen);

I just rewrote it to this in my delphi pas (statically example):

function call_libname_conv(inbuf: PChar;
                          inlen: Integer;
                          outbuf: string;
                          outlen: Integer): integer cdecl  {$IFDEF WIN32} stdcall {$ENDIF};

This works, but I wonder what the hell was the '__declspec(dllexport)'/'__declspec(dllimport)' means and if I should use it in delphi?!
A remark: I have an obvious memory leak in the DLL when I use it in my delphi project. The vendor of the DLL assured me, that he can't reproduce this
leak in his environment (I believe him, because he is very supportive). Could this be caused because of this 'wrong' conversion from the c header to my pas??


I this C header, there is an callback function (hope this is the correct name for this):

/* Progress function gets progress information, 0.0 to 100.0 ("percent") */

LIBNAME_API int _stdcall setProgressFunction(int (__stdcall *myProgressFunction)(float));

How should I convert this to pascal? I assume 'myProgressFunction' would be one of my delphi functions that is called back from the DLL and shows something like a progress bar?! How should this function call look in my pas and how should my own 'myProgressFunction' look like (just the definition)??

I know you are experts, so I'm sure there are many peoples out that are able to solve this two problems ;)

Many thanks in advance!!

Question by:real_icecoke
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
  • 2
LVL 28

Accepted Solution

2266180 earned 1000 total points
ID: 16992112
for the second problem:

type myprogressfunc(p:float):integer; stdcall;

function setProgressFunction(f:myprogressfunc):integer; stdcall; external "blala.dll";// if using static linking. if you are loading the dll dinamically, skip this one.

function myprogress(p:float):integer; stdcall;
// do whatever


for the first problem (and second):
also, I don' know if you need the cdecl. try without it and see if yo are getting any memory leaks.

the thing with the __declspec(dllexport)'/'__declspec(dllimport)' means and if I should use it in delphi?!
is that the header is used both in the program and in the dll. so the dll defines LIBNAME_EXPORTS which means that the functions will be exported and hence need the dllexport thingie.
on the otehr heand, if you use the header from your program (C) then you don't define LIBNAME_EXPORTS so it will use the dllimport.

that's about it. also, you cannot use 2 calling convensions (like you do in your case, cdecl and stdcall. you need to only use one.
LVL 26

Expert Comment

by:Russell Libby
ID: 16992379
Just as a confirmation, you should only be using stdcall:

>> LIBNAME_API int _stdcall call_libname_conv(char *inbuf, int inlen, char *outbuf, int outlen);

the _stdcall indicates that the function shall use the stdcall convention (regardless of importing/exporting the function). If you wanted to duplicate the defines in the code, then the following would be one way to do it in Delphi:

  LibName           = 'the_library.dll'; // Correct this with the import library name

function call_libname_conv(inbuf: PChar; inlen: Integer; outbuf: PChar; outlen: Integer): Integer; stdcall; {$IFNDEF LIBNAME_EXPORTS} external LibName; {$ENDIF}

The points belong to ciuly on this one though.



Author Comment

ID: 16994594
Thanks to both Russel and ciuly for the fast answer!

So, Q1 ist solved for me - thanks!
Regarding Q2 I tried to use and understand ciuly's example but failed at all. It seems that I have no clue where to place what in a unit. And further more I have to ask myself how the setProgressFunction is used. Do I have to call it, while other routines are running from this DLL (its a file conversion DLL and I assume setProgressFunction shows the state of processing) or is the DLL calling my 'myprogress(dPerct: double)' on its own??

Ciuly, do you have the time to show me a small, but functional example unit for this? Would be great!

Thanks again!
LVL 26

Assisted Solution

by:Russell Libby
Russell Libby earned 1000 total points
ID: 16994761

The defs would be similar to:

// Function prototype
  TProgressFunc  =  function(F: Single): Integer; stdcall;

// Imported function from library
function setProgressFunction(ProgressFunc: TProgressFunc): Integer; stdcall; external 'the_library.dll';

// ... other imported functions, etc...

{$R *.DFM}

// Your callback function
function MyProgress(F: Single): Integer; stdcall;
  // do whatever


You are then expected to call setProgressFunction in your program somewhere, passing it the function address that you wish to be called when some progress has occurred. In the above example, the MyProgress function is the desired callback, and to use it:

// Program code

// Tell the dll what function to call back on

// Make some call to the dll that will cause the callback function to be executed

The dll will then call your function MyProgress, where you can whatever it is you want to do. Also, it is pretty hard for any of us to provide a functional example without an actual library (and documentation) to program against.



Author Comment

ID: 17002374
Yep, that is what a dopey guy like me understands ;)
Thanks to both of you! Even if Russel stated the points belong to ciuly, I will split the points, because Russel achieved to make a blind guy seeing :)

Anyway, again thanks to both giving great answers again!


Featured Post


Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Michael from AdRem Software outlines event notifications and Automatic Corrective Actions in network monitoring. Automatic Corrective Actions are scripts, which can automatically run upon discovery of a certain undesirable condition in your network.…
This tutorial will teach you the special effect of super speed similar to the fictional character Wally West aka "The Flash" After Shake : http://www.videocopilot.net/presets/after_shake/ All lightning effects with instructions : http://www.mediaf…
Suggested Courses
Course of the Month14 days, 20 hours left to enroll

771 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