2017-02-10 14 views
1

Я пытаюсь использовать процедуры в структурированном типе данных в качестве функций обратного вызова для программы с использованием GTK + 3 в качестве своего инструментария в FreePascal. (GTK + 3 привязки я был сгенерирован инструментом gir2pascal (http://wiki.freepascal.org/gir2pascal))Использование процедуры в структурированном типе данных в качестве обратного вызова для библиотеки C (GTK + 3)

В приведенном ниже примере я использую расширенные записи, но я бы определенно рассматривал классы или объекты, если он работает лучше/вообще с ними.

Возникает проблема в том, что при вызове процедуры обратного вызова он не может получить доступ к чему-либо еще в своей собственной записи. Кажется, «забыл», откуда он исходит.

Например, в приведенном ниже примере у меня есть целое число myRecord.myInt, которое я могу установить и получить счастливо, вызвав процедуру myRecord.testProcedure. Однако, когда testProcedure используется в качестве обратного вызова C (при нажатии кнопки), я буду получать некоторое количество (например, 30976), но не 7.

{$MODESWITCH ADVANCEDRECORDS} 
uses gobject2, gtk3, math; 

type 
    myRecord=record 
    public 
     myInt: Integer; 
     procedure testProcedure; cdecl; 
    end; 

    procedure myRecord.testProcedure; cdecl; 
    begin 
    WriteLn(myInt); 
    end; 

var 
    recordInstance: myRecord; 
    button, win: PGtkWidget; 
begin 
    SetExceptionMask([exDenormalized, exInvalidOp, exOverflow, 
    exPrecision, exUnderflow, exZeroDivide]); {this is needed for GTK not to crash} 

    gtk_init(@argc, @argv); 

    win:=gtk_window_new(GTK_WINDOW_TOPLEVEL); 

    recordInstance.myInt:=7; 

    button:=gtk_button_new; 

    {The following does not work. The procedure will run when the button is 
    clicked; it will print some number, but not the content of recordInstance.myInt} 
    g_signal_connect_data(button, 'clicked', 
    TGCallback(@recordInstance.testProcedure), nil, nil, 0); 

    {add button to window} 
    gtk_container_add(PGtkContainer(win), button); 

    gtk_widget_show_all(win); 

    {Test call to recordInstance.testProcedure to see that it outputs 
    '7' correctly} 
    recordInstance.testProcedure; 

    gtk_main; 
end. 

Когда я пытаюсь использовать классы или объекты вместо Advanced Запись, я получаю сообщения об ошибках типа

"<procedure variable type of procedure of object;CDecl>" to "<procedure variable type of procedure;CDecl>" 

Какие есть пути использования структурированного типа данных с процедурой, чтобы использовать в качестве обратного вызова C, как в приведенном выше примере (если таковой имеется)?

+0

Я полагаю, что C не имеет способа использовать метод в качестве обратного вызова. Вызов метода должен быть преобразован в обычный вызов процедуры. См. [Как передать метод как ответ на вызов Windows API?] (Http://stackoverflow.com/q/2787887/576719). –

ответ

1

Статические методы класса совместимы с процедурами. Но они также имеют тот недостаток, что у них нет ссылки на данные объекта.

{$mode delphi} 

type 
    myRecord=record 
    public 
     myInt: Integer; 
     class procedure testProcedure; cdecl;static; 
    end; 

    tproctype = procedure; cdecl; 

class procedure myrecord.testProcedure; cdecl;static; 
begin 
end; 

var x : tproctype; 
    y : myrecord; 
begin 
x:=y.testprocedure; 
end. 

компилируется, но использование является стерильным, так как если он отображает в обычный C, он не имеет (неявные) свойства ОО.

 Смежные вопросы

  • Нет связанных вопросов^_^