Forum > General

[SOLVED] c callback function crash the program

(1/2) > >>

mercury:
I'm making a c lib for Pascal, but get crash on a callback function.
Where am I mistake?

libhoge.h

--- Code: C  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---int hoge_count = 0;extern int hoge1(int i);typedef void (*TCallback)(int, int);TCallback CallbackFunction;extern int hoge_SetCallback(TCallback ACallback); 
libhoge.c

--- Code: C  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---#include <stdio.h>#include <unistd.h>#include <windows.h> #include "libhoge.h" int hoge1(int i) {  printf("hoge1\n");   Sleep(1000);   if (CallbackFunction != NULL) {    printf("CallbackFunction\n");    CallbackFunction(111, 222);  }   hoge_count = hoge_count + i;  return (hoge_count);} int hoge_SetCallback(TCallback ACallback) {  printf("hoge_SetCallback\n");   CallbackFunction = ACallback;  return 1;} 

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure TForm1.FFCallback(i, j: integer); cdecl;begin  Memo1.Append(IntToStr(i) + ' - ' + IntToStr(j));  <------- crash hereend; 
Full source see the attachment.
Open .dev file with Dev-Cpp.

Thank you very much.

Thaddy:
The callback is not a procedure of object.

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---type  TFFCallback = procedure(i, j: integer) of object cdecl;// should be something like:type  TFFCallback = procedure(i, j: integer); cdecl; 
That's because a procedure of object has a hidden self  parameter and that is missing in the c code:

--- Code: Javascript  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---typedef void (*TCallback)(int, int);// should look like this for procedure of object, but I would not do it like that:typedef void (*TCallback)(void * , int, int);It really looks like:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---type  TFFCallback = procedure(_self, i, j: integer);cdecl;  //pseudo code So either take care that the C code reflects that hidden parameter or do away with it.


It is also not necessary. So simply remove of object.

skalogryz:
In C you're declaring a callback function, but in pascal you declared it as a callback method.

You pretty much lied to yourself! By the time the callback is called there's no "self" parameter. A rubbish data is there, so calling to any property of the form (in your case it's Memo1.Add.. ) causes an access violation.

If you look at all possible C libraries, apart from Callback function they're typically accepting a callback data. The data is typically size of a pointer or a pointer itself. The data is also passed to callback function.
This approach is utilized in OOP to pass the reference to the object into the routine and later to be received as a callback parameter.

With that said, there're two ways on how to do that.
1) Using Global variables and not changing C.
1.1 change your libhoge.pas declaration as following:

--- Code: ---type
  TFFCallback = procedure(i, j: integer) cdecl;

...
function hoge_SetCallback(ACallback: TFFCallback): longint;
  cdecl; external {$IFDEF shared}External_library{$ENDIF} Name 'hoge_SetCallback';

--- End code ---

1.2 Modify your Unit1 code as following:

--- Code: ---procedure FFCallbackForForm1(i,j: integer); cdecl;
begin
  Form1.FFCallback(i,j);
end;

procedure TForm1.BtnHoge_SetCallbackClick(Sender: TObject);
begin
  hoge_SetCallback(@FFCallbackForForm1);
end;

procedure TForm1.FFCallback(i, j: integer);
begin
  Memo1.Append(IntToStr(i) + ' - ' + IntToStr(j));
end;

--- End code ---
2) Rewrite your library callback function to accept a "data" parameter (a pointer). and pass the same "data" at the time the callback is called.
In your pascal code, pass the reference to TForm as a data, and cast the data back to TForm within the callback.


Thaddy:
Basically the same as I wrote. Our messages crossed. Thanks for pointing out he really needs a function to obtain the result. I overlooked that.

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---type  TFFCallback = function (i, j: integer):integer; cdecl; 
It is possible to use that as a class member when it would be a class function.

skalogryz:

--- Quote from: Thaddy on March 06, 2016, 08:05:15 am ---Basically the same as I wrote. Our messages crossed. Thanks for pointing out he really needs a function to obtain the result. I overlooked that.

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---type  TFFCallback = function (i, j: integer):integer; cdecl; 
It is possible to use that as a class member when it would be a class function.

--- End quote ---
wait wait. TFFCallback is not function it's a procedure for pascal (void is used as the return type)

but the function hoge_SetCallback() is a function.

It's easy to cross on such question, requiring extensive answer :)

Navigation

[0] Message Index

[#] Next page

Go to full version