Hi all,
I define a procedure like this:
type
TDataHandler = procedure(data: Pointer) of object;
procedure SetHandler(h: TDataHandler); external cdecl;Now, can I implement SetHandler in a library written in C, then call h in C?
Thankyou.

Mailing lists / fpc-pascal / 2015-03
9 messages · 6 people · –
Reply by email Subscribe to this list Your subscription
Read-only archive. Use j and k to move between messages.
Hi all,
I define a procedure like this:
type
TDataHandler = procedure(data: Pointer) of object;
procedure SetHandler(h: TDataHandler); external cdecl;Now, can I implement SetHandler in a library written in C, then call h in C?
Thankyou.
IMHO Not without separate assembler code for each CPU.
Michael.
How about using TMethod?
procedure DataHandler(DummySelf: Pointer; data: Pointer);
begin
// do what you want to do, DummySelf is always nil.
end;
var
Method: TMethod;
begin
Method.Data := nil;
Method.Code := @DataHandler;
SetHandler(TDataHandler(Method));
end;You must be sure that self is passed in the correct register. I am not sure this is the case if you declare it as an extra argument. It may be so, but compiler people should confirm this. I don't think you can take it for granted.
Michael.
Michael Van Canneyt wroteYou must be sure that self is passed in the correct register. I am not sure this is the case if you declare it as an extra argument.
It is, as long as the `self` is the first parameter. Same goes for `Class Procedure XXX;` kind of declarations (in constrast to `Class procedure XXX; static;`).
I don't know how long that is going to last however (since this hidden parameter thingy is an implementation detail of the compiler I think). So I fully agree: it would be a kindness of the compiler people to confirm this :-)
How about using TMethod? procedure DataHandler(DummySelf: Pointer; data: Pointer); begin…
2015-03-10 0:33 GMT+08:00 OBones :
I'm not sure how this works, but it seems that you are deliberately converting a normal procedure to a method. What I want is exactly opposite
- I want to convert a method to a normal procedure.
If I define the interfact of DataHandler like this:
TDataHandler = procedure(data: Pointer); cdecl;It is very easy to use in an so, no matter it is written in C or pascal.
But the problem is, I want to do this:
SetHandler(h);where h is a METHOD, not a normal procedure.
Because I want to use the handler wrapped in my Class.
However, like in my first mail, if I define THandler a procedure of object, it makes easier to SetHandler(AMethod); but how can I use that "procedure of object" pointer in the so?
Thanks!
I define a procedure like this: type TDataHandler = procedure(data: Pointer) of object;…
Xiangrong Fang wrotecan I implement SetHandler in a library written in C, then call h in C?
For inter-language calls you obviously need to to define the calling style on both sites. e.g. "STDCALL" or "PASCAL", to make both use compatible calling conventions.
I don't know if/how such keywords exist for "procedure of object" style of functions (and hence for the types of the variables pointers to them are stored in).
If not you should use a "flat" calling scheme: on both sites use standard (non-object) functions with e.g. "STDCALL" (adding/extracting the Self pointer explicitly on the way, if appropriate). Regarding variables for holding (pointers to) such functions they need to be a record of a (flat) function pointer plus a Self pointer.
This said, you can't (easily) pass objects to a C library, anyway, as the memory management is not synchronized by default. Like with Pascal Strings, a e.g. Free will lead into chaos.
-Michael
2015-03-10 0:33 GMT+08:00 OBones : I'm not sure how this works, but it seems that you…
Xiangrong Fang wroteHowever, like in my first mail, if I define THandler a procedure of object, it makes easier to SetHandler(AMethod); but how can I use that "procedure of object" pointer in the so?
It works the same, cast the data you receive to a TMethod and call the "code" member with the appropriate parameters. So, in the "C" library do this:
typedef struct
{
Data: Pointer;
Code: Pointer;
}TMethod;
void SetHandler(TMethod h);
{
StoredH = h;
}
typedef void (*TDataHandler)(void* Self, void* Data);
void DoSomething();
{
((TDataHandler)(StoredH.Code))(StoredH.Data, SomeData);
}Warning, this is pseudo code, you should adapt it so that it can compile.
Note that you have to make sure that you declare your "procedure of object" as "cdecl" in that case, and as a result you'll also have to declare all methods that you want to assign to this procvar as "cdecl".
Jonas