converting C header to delphi; callback function definition in delphi

Posted on 2006-06-27
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 250 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 250 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

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering 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

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
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…
There's a multitude of different network monitoring solutions out there, and you're probably wondering what makes NetCrunch so special. It's completely agentless, but does let you create an agent, if you desire. It offers powerful scalability …
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.…

729 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