Solved

converting C header to delphi; callback function definition in delphi

Posted on 2006-06-27
5
695 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
[X]
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
5 Comments
 
LVL 28

Accepted Solution

by:
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;
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

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

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…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
A short tutorial showing how to set up an email signature in Outlook on the Web (previously known as OWA). For free email signatures designs, visit https://www.mail-signatures.com/articles/signature-templates/?sts=6651 If you want to manage em…
Are you ready to implement Active Directory best practices without reading 300+ pages? You're in luck. In this webinar hosted by Skyport Systems, you gain insight into Microsoft's latest comprehensive guide, with tips on the best and easiest way…

732 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