[Lazarus] Callback and Threads problem

Antonio Fortuny a.fortuny at sitasoftware.lu
Fri Apr 6 16:05:34 CEST 2012



Le 06/04/2012 15:04, Leonardo M. Ramé a écrit :
> On 2012-04-06 14:53:13 +0200, michael.vancanneyt at wisa.be wrote:
>>
>> On Fri, 6 Apr 2012, Leonardo M. Ramé wrote:
>>
>>> On 2012-04-06 14:39:10 +0200, michael.vancanneyt at wisa.be wrote:
>>>>
>>>> On Fri, 6 Apr 2012, Leonardo M. Ramé wrote:
>>>>
>>>>> I have a similar problem to this:
>>>>>
>>>>> http://www.lazarus.freepascal.org/index.php?topic=10571.0
>>>>>
>>>>> My main program launches a thread, that loads a shared library, then
>>>>> execute a function who receives as a parameter a pointer to a callback
>>>>> function and an instance of the caller, as this:
>>>>>
>>>>> procedure TMythread.execute;
>>>>> begin
>>>>> ...
>>>>> // external function
>>>>> runcode(@MyCallBack, @Self);
>>>>> ...
>>>>> end;
>>>>>
>>>>> procedure MyCallback(const Result: PAnsiChar; const ACaller: pointer);
>>>>> cdecl;
>>>>> var
>>>>> lCaller: TMythread;
>>>>> begin
>>>>> // the parameter ACaller is used because callbacks can't be of type
>>>>> // procedure of object.
>>>>> lCaller := TMyThread(ACaller);
>>>>> lCaller.TestVar := Result; //<--- Ok.
>>>>> lCaller.ListOfThings.Add;  //<--- SIGSEGV
>>>> IMHO the problem is not in threads.
>>>>
>>>> You cannot pass objects to libraries or vice versa.
>>>> The VMTs will differ.
>>>>
>>>> Michael.
>>> But, I'm passing the object as a pointer that is received as (void *) and
>>> returned back to the callback as a parameter, the library doesn't touch
>>> it. Even in this case I can't pass an object?.
>> Ah. In that case you can, yes.
>>
>> Is the calling convention correct ?
>>
>> Michael.
> Yes, I'm using cdecl.
>
> BTW. I somewhat fixed the issue by defining a global variable of the
> same type of my thread, the var points to "Self" just before calling the
> external function and assigned to nil when the function ends.
Not exactly a fix but the good way. If I undertsand well, with this form:
runcode(@MyCallBack, @Self);
the second parameter is not a pointer pointing to some address but the 
address itself.

doing a previous
var
     PP: Pointer;
anf then
pp := @MyThread
runcode(@MyCallBack, pp);
passes a real pointer whose data effectively points to the desired 
object (the thread in the example).
I wonder if the same rule applies to the first paramaeter

This can explain why your second method works.

Antonio.


>
> This way, the callback can use the thread by pointing to the global var.
>
> I hate to use global variables, but, as the function is called only
> once, I know it won't be overlapped by many callers.
>
> Regards,






More information about the Lazarus mailing list