Seite 1 von 1

TOBII-Eye-Tracker => C-Source + Header in PB übertragen

Verfasst: 11.09.2018 15:08
von HW-SW-Tüftler
Hallo,

momentan beschäftige ich mich mit der TOBII-Augensteuerung (siehe: https://tobiigaming.com/product/tobii-eye-tracker-4c/), die ich in eigene bestehende Purebasic-Programme einbinden möchte.

Die Low-Level-API mit den entsprechenden DLL's und Header-Dateien habe ich unter https://www.nuget.org/packages/Tobii.St ... ne.Native/ heruntergeladen. Die Online-Dokumentation ist unter https://github.com/Tobii/stream_engine/ ... s/index.md verfügbar. Offline kann die API-Reference auch als PDF-Datei im nupkg-Paket eingesehen werden.

In C funktionieren auch bereits alle Beispiel-Programme, die in der API-Reference aufgeführt sind (getestet mit PellesC).
Nun möchte ich diese C-Programme inkl. Header-Dateien in Purebasic übertragen.

Mit dem in Purebasic/SDK enthaltenen HeaderConverter wird ja schon so einiges korrekt in Purebasic überführt, aber es gibt noch Ausnahmen, die dann zu Fehlermeldungen führen. Wenn man sich mit den C-Header-Dateien (hier tobii.h) beschäftigt, stößt man u.a. auf solche Zeilen:

Code: Alles auswählen

typedef struct tobii_api_t tobii_api_t;
typedef struct tobii_engine_t tobii_engine_t;
typedef struct tobii_device_t tobii_device_t;
Sonst tauchen die Namen nirgends mehr in der Header-Datei auf, es wird nirgends eine Struktur definiert. Was macht der C-Compiler damit, wie bekomme ich das in Purebasic übersetzt? (Der Header-Converter ignoriert / übersetzt diese Zeilen z.B. nicht)

Kann mir da jemand helfen?


Die gesamte tobii.h-Headerdatei lässt sich wegen der Größe (hier max. 60000 Zeichen) leider nicht einfügen. Ist im nupkg-Paket enthalten, was unter https://www.nuget.org/packages/Tobii.St ... ne.Native/ heruntergeladen werden kann.

Letztlich soll das einfachste Beispiel-Programm (API-SS öffnen, Device-URLs enumerieren, Device-SS öffnen, Device-Info lesen, Device-SS aus Speicher entfernen, API-SS aus Speicher entfernen) in Purebasic zum Laufen kommen.

Hier ein entsprechender C-Sourcecode:

Code: Alles auswählen

#include <tobii/tobii.h>
#include <assert.h>
#include <stdio.h>


static void url_receiver( char const* url, void* user_data )
{
	char* buffer = (char*)user_data;
	if( *buffer != '\0' ) return; // only keep first value
	if( strlen( url ) < 256 )
	strcpy( buffer, url );
}


int main()
{
	tobii_api_t* api;
	tobii_error_t error = tobii_api_create( &api, NULL, NULL );
	assert( error == TOBII_ERROR_NO_ERROR );
	char url[ 256 ] = { 0 };
	error = tobii_enumerate_local_device_urls( api, url_receiver, url );
	assert( error == TOBII_ERROR_NO_ERROR && *url != '\0' );
	tobii_device_t* device;
	error = tobii_device_create( api, url, &device );
	assert( error == TOBII_ERROR_NO_ERROR );
	tobii_device_info_t info;
	error = tobii_get_device_info( device, &info );
	assert( error == TOBII_ERROR_NO_ERROR );
	printf( "Serial number: %s\n", info.serial_number );
	error = tobii_device_destroy( device );
	assert( error == TOBII_ERROR_NO_ERROR );
	error = tobii_api_destroy( api );
	assert( error == TOBII_ERROR_NO_ERROR );
	return 0;
} 
Mein bislang erstellter Purebasic-Code-Rumpf sieht so aus:

Code: Alles auswählen

;*****************************************************************************************************
;*                             TOBII-Augensteuerung_Evaluierung                                      *
;*                                                                                                   *
;*  evaluiert das Interface zur TOBII-Augensteuerung per NATIVE-C-API                                *
;*  siehe: https://www.nuget.org/packages/Tobii.StreamEngine.Native/                                 *
;*         (=> Native-C_API-Reference.pdf)                                                           *
;*                                                                                                   *
;*  Die Versionsangabe wird in der Titelzeile des Fensters angezeigt.                                *
;*                                                                                                   *
;*  erstellt mit Purebasic 5.46 LTS  am  12.07.2018                                                  *
;*****************************************************************************************************

XIncludeFile "...Pfadangabe...\tobii.pbi"


EnableExplicit

;****************************************** enumerierte Konstanten *******************************************************

;*** Fenster ******
Enumeration
   #Haupt_Fenster
EndEnumeration

;*** Statusbars ***
Enumeration
   #StatusBar_Hauptfenster
EndEnumeration

;*** Libraries ***
Enumeration
   #tobii_stream_engine_dll
EndEnumeration

;****************************************** Variablen *****************************************************************
Global ProgPfad$       = ""
Global ProgPfad_nackt$ = ""
Global ProgName_nackt$ = ""
Global DatumZeit$      = ""
Global WindowTitel1$   = ""
Global WindowTitel2$   = ""
Global WindowTitel$    = ""
Global DesktopBreite.l = 0
Global DesktopHoehe.l  = 0
Global FensterBreite.l = 0
Global FensterHoehe.l  = 0
Global Event.l         = 0

Global *api_create, *enumerate_local_device_urls, *device_create, *get_device_info, *device_destroy, *api_destroy     ;Zeiger auf die genutzten DLL-Funktionen in der "tobii_stream_engine.dll"
Global lib_ok = 0

Global Fehlercode.l = 0

;****************************************** Hauptprogramm ***********************************************************************
ProgPfad$ = ProgramFilename()
ProgPfad_nackt$ = GetPathPart(ProgPfad$)
ProgName_nackt$ = GetFilePart(ProgPfad$)
DatumZeit$ = FormatDate("%dd.%mm.%yyyy  ;  %hh:%ii:%ss", GetFileDate(ProgPfad$, #PB_Date_Created))
WindowTitel1$ = "Evaluierung TOBII Gaze Eye-Tracker (Augensteuerung)    Version: " + DatumZeit$
WindowTitel2$ = "    kompiliert mit Purebasic " + Left(Str(#PB_Compiler_Version), 1) + "." + Right(Str(#PB_Compiler_Version), 2)
WindowTitel$ = WindowTitel1$ + WindowTitel2$

If ExamineDesktops()
   DesktopBreite = DesktopWidth(0)
   DesktopHoehe = DesktopHeight(0)
EndIf
FensterBreite = DesktopBreite - 14
FensterHoehe  = DesktopHoehe  - 66

If OpenWindow(#Haupt_Fenster, 3, 0, FensterBreite, FensterHoehe, WindowTitel$, #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget)
   
   
   If CreateStatusBar(#StatusBar_Hauptfenster, WindowID(#Haupt_Fenster))
      AddStatusBarField(0.84*DesktopBreite)
      AddStatusBarField(#PB_Ignore)
      StatusBarText(#StatusBar_Hauptfenster, 1, "Desktop-Auflösung: "+ DesktopBreite + " x " + DesktopHoehe)
   EndIf

   
   ;tobii_stream_engine.dll öffnen...
   If OpenLibrary(#tobii_stream_engine_dll, "tobii_stream_engine.dll") 
      *api_create                   = GetFunction (#tobii_stream_engine_dll,"tobii_api_create")                    ;Zeiger auf Funktion zur Erstellung der API-Schnittstelle
      *enumerate_local_device_urls  = GetFunction (#tobii_stream_engine_dll,"tobii_enumerate_local_device_urls")   ;Zeiger auf Funktion zum Enumerieren der URLs der Augensteuerungs-Devices, wenn ggf. mehrere vorhanden...
      *device_create                = GetFunction (#tobii_stream_engine_dll,"tobii_device_create")                 ;Zeiger auf Funktion zum Erstellen der Schnittstelle zum Device
      *get_device_info              = GetFunction (#tobii_stream_engine_dll,"tobii_get_device_info")               ;Zeiger auf Funktion zum Abfragen der Device-Information
      *device_destroy               = GetFunction (#tobii_stream_engine_dll,"tobii_device_destroy")                ;Zeiger auf Funktion zum Entfernen der Schnittstelle zum Device aus dem Speicher
      *api_destroy                  = GetFunction (#tobii_stream_engine_dll,"tobii_api_destroy")                   ;Zeiger auf Funktion zum Entfernen der Schnittstelle zur API aus dem Speicher

      If  *api_create And *enumerate_local_device_urls And *device_create And *get_device_info And *device_destroy And *api_destroy
         lib_ok=1
         MessageRequester("tobii_stream_engine.dll","Es wurden alle angeforderten Funktionen in der <tobii_stream_engine.dll> gefunden!",#PB_MessageRequester_Ok)     ;alle Funktionen gefunden, Statusvariable lib_ok=1
      Else 
         CloseLibrary(#tobii_stream_engine_dll)
         MessageRequester("tobii_stream_engine.dll","Es konnten nicht alle angeforderten Funktionen in der <tobii_stream_engine.dll> gefunden werden!",#PB_MessageRequester_Ok) 
         End
      EndIf 
   Else
      MessageRequester("tobii_stream_engine.dll","Bibliothek <tobii_stream_engine.dll> konnte nicht geöffnet werden",#PB_MessageRequester_Ok) 
      End
   EndIf

   Define *api.tobii_api_t

   Fehlercode = CallFunctionFast(*api_create, 0, 0)
   Select Fehlercode
      Case 0
         MessageRequester("Fehlercode-Anzeige","Das API-Interfaces wurde erfolgreich erstellt. Fehlercode "+Str(Fehlercode)+": " +  "#TOBII_ERROR_NO_ERROR",#PB_MessageRequester_Ok)
         Fehlercode = CallFunctionFast(*api_destroy)
      Case 1
         MessageRequester("Fehlercode-Anzeige","Beim Erstellen des API-Interfaces wurde der Fehlercode "+Str(Fehlercode)+" zurückgegeben: " +  "#TOBII_ERROR_INTERNAL",#PB_MessageRequester_Ok)
      Case 2
         MessageRequester("Fehlercode-Anzeige","Beim Erstellen des API-Interfaces wurde der Fehlercode "+Str(Fehlercode)+" zurückgegeben: " +  "#TOBII_ERROR_INSUFFICIENT_LICENSE",#PB_MessageRequester_Ok)
      Case 3
         MessageRequester("Fehlercode-Anzeige","Beim Erstellen des API-Interfaces wurde der Fehlercode "+Str(Fehlercode)+" zurückgegeben: " +  "#TOBII_ERROR_NOT_SUPPORTED",#PB_MessageRequester_Ok)
      Case 4
         MessageRequester("Fehlercode-Anzeige","Beim Erstellen des API-Interfaces wurde der Fehlercode "+Str(Fehlercode)+" zurückgegeben: " +  "#TOBII_ERROR_NOT_AVAILABLE",#PB_MessageRequester_Ok)
      Case 5
         MessageRequester("Fehlercode-Anzeige","Beim Erstellen des API-Interfaces wurde der Fehlercode "+Str(Fehlercode)+" zurückgegeben: " +  "#TOBII_ERROR_CONNECTION_FAILED",#PB_MessageRequester_Ok)
      Case 6
         MessageRequester("Fehlercode-Anzeige","Beim Erstellen des API-Interfaces wurde der Fehlercode "+Str(Fehlercode)+" zurückgegeben: " +  "#TOBII_ERROR_TIMED_OUT",#PB_MessageRequester_Ok)
      Case 7
         MessageRequester("Fehlercode-Anzeige","Beim Erstellen des API-Interfaces wurde der Fehlercode "+Str(Fehlercode)+" zurückgegeben: " +  "#TOBII_ERROR_ALLOCATION_FAILED",#PB_MessageRequester_Ok)
      Case 8
         MessageRequester("Fehlercode-Anzeige","Beim Erstellen des API-Interfaces wurde der Fehlercode "+Str(Fehlercode)+" zurückgegeben: " +  "#TOBII_ERROR_INVALID_PARAMETER",#PB_MessageRequester_Ok)
      Case 9
         MessageRequester("Fehlercode-Anzeige","Beim Erstellen des API-Interfaces wurde der Fehlercode "+Str(Fehlercode)+" zurückgegeben: " +  "#TOBII_ERROR_CALIBRATION_ALREADY_STARTED",#PB_MessageRequester_Ok)
      Case 10
         MessageRequester("Fehlercode-Anzeige","Beim Erstellen des API-Interfaces wurde der Fehlercode "+Str(Fehlercode)+" zurückgegeben: " +  "#TOBII_ERROR_CALIBRATION_NOT_STARTED",#PB_MessageRequester_Ok)
      Case 11
         MessageRequester("Fehlercode-Anzeige","Beim Erstellen des API-Interfaces wurde der Fehlercode "+Str(Fehlercode)+" zurückgegeben: " +  "#TOBII_ERROR_ALREADY_SUBSCRIBED",#PB_MessageRequester_Ok)
      Case 12
         MessageRequester("Fehlercode-Anzeige","Beim Erstellen des API-Interfaces wurde der Fehlercode "+Str(Fehlercode)+" zurückgegeben: " +  "#TOBII_ERROR_NOT_SUBSCRIBED",#PB_MessageRequester_Ok)
      Case 13
         MessageRequester("Fehlercode-Anzeige","Beim Erstellen des API-Interfaces wurde der Fehlercode "+Str(Fehlercode)+" zurückgegeben: " +  "#TOBII_ERROR_OPERATION_FAILED",#PB_MessageRequester_Ok)
      Case 14
         MessageRequester("Fehlercode-Anzeige","Beim Erstellen des API-Interfaces wurde der Fehlercode "+Str(Fehlercode)+" zurückgegeben: " +  "#TOBII_ERROR_CONFLICTING_API_INSTANCES",#PB_MessageRequester_Ok)
      Case 15
         MessageRequester("Fehlercode-Anzeige","Beim Erstellen des API-Interfaces wurde der Fehlercode "+Str(Fehlercode)+" zurückgegeben: " +  "#TOBII_ERROR_CALIBRATION_BUSY",#PB_MessageRequester_Ok)
      Case 16
         MessageRequester("Fehlercode-Anzeige","Beim Erstellen des API-Interfaces wurde der Fehlercode "+Str(Fehlercode)+" zurückgegeben: " +  "#TOBII_ERROR_CALLBACK_IN_PROGRESS",#PB_MessageRequester_Ok)
      Case 17
         MessageRequester("Fehlercode-Anzeige","Beim Erstellen des API-Interfaces wurde der Fehlercode "+Str(Fehlercode)+" zurückgegeben: " +  "#TOBII_ERROR_TOO_MANY_SUBSCRIBERS",#PB_MessageRequester_Ok)
   EndSelect
   
   Repeat
      Event = WindowEvent()
      
      If Event <> 0  ;Alle Ereignisse
         SetWindowTitle(#Haupt_Fenster, WindowTitel$ + Space(30) + "Maus-Koordinaten: " + Str(WindowMouseX(#Haupt_Fenster)) + "," + Str(WindowMouseY(#Haupt_Fenster))) 
      Else
         
         Delay(1)
      EndIf
   Until Event = #PB_Event_CloseWindow
   If lib_ok=1
      CloseLibrary(#tobii_stream_engine_dll)
   EndIf
EndIf

End
Die CallFunctionFast-Aufrufe will ich auf jeden Fall noch in eine Lösung mit Prototypes ändern, aber momentan ist mir überhaupt nicht klar, was da im Speicher wo und wie bereitzustellen ist.

Bin für jede Hilfe dankbar!

Re: TOBII-Eye-Tracker => C-Source + Header in PB übertragen

Verfasst: 25.11.2018 15:07
von DarkSoul
Deine typedef's sehen sinnloser aus, als sie tatsächlich sind.

Damit wird die Struktur zum neuen Datentyp erklärt. Die heißen sinnvollerweise gleich. <)

Code: Alles auswählen

struct bla_blubb 
{
  int a;
  int b;
};

//um eine Variable mit dieser Struktur zu bekommen:
struct bla_blubb eine_variable;

//jetzt kommt dein typedef struct
typedef struct bla_blubb bla_blubb;

//ab jetzt bekommt man eine Variable auch so, was besser und übersichtlicher aussieht:
bla_blubb noch_eine_variable;

//Hier mal in Trennzeichen, um es anschaulicher zu machen:
typedef | struct bla_blubb | bla_blubb; //= Erkläre die Struktur bla_blubb zu einem neuen Datentyp namens bla_blubb.
Ansonsten muss die Struktur irgendwo definiert sein. Das muss nicht zwangsläufig in dieser Datei sein. Sonst würde der Compiler sagen: Kenne ich nicht, will ich nicht, und tschüß.... Weitersuchen bzw. Doku/Internet danach absuchen und dann mit den PB-Gegenstücken nachbauen. :)