2017-02-10 4 views
1

FreePascal에서 툴킷으로 GTK + 3을 사용하는 프로그램의 콜백 함수로 구조화 된 데이터 형식 내의 프로 시저를 사용하려고합니다. (내가 가지고있는 GTK + 3 바인딩은 gir2pascal 도구 (http://wiki.freepascal.org/gir2pascal)에 의해 생성되었습니다.C 라이브러리 (GTK + 3)에 대한 콜백으로 구조화 된 데이터 형식의 프로 시저 사용

아래 예제에서는 고급 레코드를 사용하지만, 클래스/오브젝트가 더 좋거나/전혀 사용되지 않는다면 확실히 고려할 것입니다.

발생하는 문제는 콜백 프로 시저가 호출 될 때 자체 레코드 내의 다른 항목에 액세스 할 수 없다는 것입니다. 그것은 "잊어 버린"것으로 보인다.

예를 들어, 아래 예제에서 정수 myRecord.myInt가 있습니다. 이는 myRecord.testProcedure 프로 시저를 호출하여 행복하게 설정하고 검색 할 수 있습니다. (I 버튼을 클릭 할 때) 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. 

때 기록, 나는 위의 예 (있는 경우)와 같이 거기에 C 콜백으로 사용할 수있는 절차를 구조화 된 데이터 유형을 사용하여 무엇 가지 종류

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

의 오류 메시지가 나타납니다?

+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로 매핑하고있는 경우에, 그것은 (암시) OO 속성을 가지고 있지 않기 때문에 사용이 멸균입니다.