Solved

converting C header to delphi; callback function definition in delphi

Posted on 2006-06-27
5
670 Views
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.

1.
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:

#ifdef LIBNAME_EXPORTS
#define LIBNAME_API __declspec(dllexport)
#else
#define LIBNAME_API __declspec(dllimport)
#endif

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??



2.

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!!
icecoke





0
Comment
Question by:real_icecoke
  • 2
  • 2
5 Comments
 
LVL 28

Accepted Solution

by:
ciuly 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;
begin
// do whatever
end;

....
  setProgressFunction(myprogress);
...

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.
0
 
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:

{$IFNDEF LIBNAME_EXPORTS}
const
  LibName           = 'the_library.dll'; // Correct this with the import library name
{$ENDIF}

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.

Regards,
Russell

0
 
LVL 1

Author Comment

by:real_icecoke
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!
icecoke
0
 
LVL 26

Assisted Solution

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

The defs would be similar to:

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

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

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

implementation
{$R *.DFM}

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

-------------

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
setProgressFunction(@MyProgress);

// 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.


Russell

0
 
LVL 1

Author Comment

by:real_icecoke
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!

icecoke
0

Featured Post

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

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…
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…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…

758 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

19 Experts available now in Live!

Get 1:1 Help Now