Funktion aus CoreFoundation funktioniert unzuverlässig

MAC OSX spezifisches Forum
Beiträge, die plattformübergreifend sind, gehören ins 'Allgemein'-Forum.
nueh
Beiträge: 12
Registriert: 12.05.2013 18:57
Wohnort: Bremen

Funktion aus CoreFoundation funktioniert unzuverlässig

Beitrag von nueh »

Hallo an alle,

ich bin erst kürzlich über PureBasic gestolpert, aber habe bislang ne Menge Spaß damit. Vieles ist mir noch nicht klar, unter anderem das Importieren von Funktionen.
Der folgende Code funktioniert in dieser Form prima. Wenn ich aber versuche, ihn in eine Include-Datei (.pbi) zu stecken, liefert

Code: Alles auswählen

CFLocaleGetWindowsLocaleCodeFromLocaleIdentifier
nichts zurück.

Hat jemand von Euch eine Idee?

Code: Alles auswählen

;
;   Mac OS X - Map a locale identifier to a Windows LCID.
; 

ImportC "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation"
  CFStringCreateWithCString(l1,s1.s,l2)
  CFLocaleGetWindowsLocaleCodeFromLocaleIdentifier(l1)
EndImport

Procedure.s getCurrentLocale()
  Protected CurrentLocale, LanguageCode, Language.s
  
  CurrentLocale = CocoaMessage(0, 0, "NSLocale currentLocale")  
  LanguageCode = CocoaMessage(0, CurrentLocale, "localeIdentifier")
  Language = PeekS(CocoaMessage(0, LanguageCode, "UTF8String"), -1, #PB_UTF8)
  
  ProcedureReturn Language
EndProcedure

Procedure.s convertLocaleToLCID(locale.s)
  Protected lcid.i
 ;-----------------  hier ist das Problem ----------------- 
  lcid = CFLocaleGetWindowsLocaleCodeFromLocaleIdentifier(CFStringCreateWithCString(0, locale, 0))
:-----------------------------------------------------
  If lcid
    ProcedureReturn Str(lcid)
  Else
    ProcedureReturn "2057" ; en_GB, Hex: 0809, Dec: 2057
  EndIf
EndProcedure

LCID.s = convertLocaleToLCID(getCurrentLocale())

Debug getCurrentLocale()
Debug LCID
Viele Grüße
nueh
PureBasic 5.40 LTS (x64), MacBook Air, Mac OS X 10.11.1
Benutzeravatar
Shardik
Beiträge: 738
Registriert: 25.01.2005 12:19

Re: Funktion aus CoreFoundation funktioniert unzuverlässig

Beitrag von Shardik »

nueh hat geschrieben:Der folgende Code funktioniert in dieser Form prima. Wenn ich aber versuche, ihn in eine Include-Datei (.pbi) zu stecken, liefert

Code: Alles auswählen

CFLocaleGetWindowsLocaleCodeFromLocaleIdentifier
nichts zurück.

Hat jemand von Euch eine Idee?
Leider kann ich Dein Problem nicht reproduzieren. Sowohl Dein Beispiel-Code als auch Dein über IncludeFile aufgerufener Beispiel-Code funktionieren bei mir immer absolut zuverlässig (getestet unter Snow Leopard 10.6.8 und Mountain Lion 10.8.3 jeweils mit PB 5.11 x86 und PB 5.11 x64).

Mir ist lediglich ein kleiner Fehler aufgefallen, der allerdings nicht die von Dir beschriebenen Auswirkungen haben sollte: Du deklarierst lcid als Integer. Laut der Header-Datei CFLocale.h ist der Rückgabewert der Funktion CFLocaleGetWindowsLocaleCodeFromLocaleIdentifier() aber ein uint32_t und müßte daher als Long definiert werden.

Zwei weitere kleine Tipps, die Tipparbeit ersparen:
- Es reicht ein ImportC "", d.h. der Pfad zum CoreFoundation-Framework muß nicht angegeben werden
- Du brauchst CFStringCreateWithCString() nicht zu importieren, denn dies ist eine der wenigen in PB vordeklarierten Funktionen: ein angehängter Unterstrich hinter dem Funktionsnamen reicht: CFStringCreateWithCString_()

Vielleicht solltest Du auch einmal Dein Beispiel mit der Include-Datei zeigen, damit ich genau dieses Beispiel einmal testen kann...
nueh
Beiträge: 12
Registriert: 12.05.2013 18:57
Wohnort: Bremen

Re: Funktion aus CoreFoundation funktioniert unzuverlässig

Beitrag von nueh »

Shardik hat geschrieben: Sowohl Dein Beispiel-Code als auch Dein über IncludeFile aufgerufener Beispiel-Code funktionieren bei mir immer absolut zuverlässig (getestet unter Snow Leopard 10.6.8 und Mountain Lion 10.8.3 jeweils mit PB 5.11 x86 und PB 5.11 x64).
Danke für die Antwort und die Mühe.

Es geht um diesen Code aus dem englischen Forum. Peinlicherweise hatte ich vorher nicht mit einem Minimalbeispiel getestet, das habe ich jetzt nachgeholt. Und siehe da: Alles funktioniert. Das Problem muss also irgendwo in meiner noch etwas chaotischen Hauptdatei liegen.
Allerdings drängt das nicht so sehr, weil mir (noch peinlicher) gerade aufgefallen ist, dass ich das ganze Windows-LCID-Gebamsel ja überhaupt nicht brauche und direkt den lokale code nutzen kann.
Du brauchst CFStringCreateWithCString() nicht zu importieren, denn dies ist eine der wenigen in PB vordeklarierten Funktionen: ein angehängter Unterstrich hinter dem Funktionsnamen reicht.
Kann ich irgendwo nachlesen, welche Funktionen vordeklariert sind? In der Hilfe ist es mir nicht aufgefallen. Und Danke auch für die anderen Tipps.

Viele Grüße
nueh
PureBasic 5.40 LTS (x64), MacBook Air, Mac OS X 10.11.1
Benutzeravatar
Shardik
Beiträge: 738
Registriert: 25.01.2005 12:19

Re: Funktion aus CoreFoundation funktioniert unzuverlässig

Beitrag von Shardik »

nueh hat geschrieben:Kann ich irgendwo nachlesen, welche Funktionen vordeklariert sind?
Leider kenne ich keine zuverlässige Möglichkeit. Normalerweise sind die API-Funktionen im PureBasic-Verzeichnis unter compilers/apifunctions.txt aufgeführt. Allerdings sind die dort aufgeführten Funktionen nicht gut gepflegt und man sollte sich nicht darauf verlassen. Sie erscheinen zwar in der Auto-Vervollständigungsliste, wenn man unter "Preferences.../Editor/Automatisches Vervollständigen/Angezeigte Einträge" auf der rechten Seite "API-Funktionen" mit einem Häkchen versehen hat. Aber in apifunctions.txt sind z.B. auch noch massig Gtk-Funktionen aufgeführt, die aber laut Fred in der Mac-Version schon lange nicht mehr unterstützt werden. Und von den String-Funktionen der CoreFoundation ist dort keine einzige aufgeführt. Ich habe daher bisher immer nach Versuch und Irrtum gearbeitet und eine API-Funktion wie z.B. CFStringCreateWithCString_() in meinem Sourcecode ausprobiert und - wenn eine Fehlermeldung kam - den Unterstrich gelöscht und die Funktion in den ImportC-Block eingetragen...

Nachtrag: Ich habe doch noch etwas gefunden als ich mit einem Hex-Editor in PureBasic-Bibliotheken herumgesucht habe. Und zwar scheinen einige CFString-Funktionen im PureBasic-Verzeichnis unter compilers/stringutility.a definiert zu sein. Die folgenden API-Funktionen sind in dieser Bibliothek aufgeführt:

- CFStringCreateWithCString()
- CFStringCreateWithBytes()
- CFStringGetBytes()
- CFStringGetLength()

Mit Unterstrich und ohne mit ImportC importiert werden zu müssen funktionieren nur diese beiden Funktionen, sodass sehr fraglich ist, ob in stringutility.a die PB-weite Definition stattfindet:

- CFStringCreateWithCString_()
- CFStringCreateWithBytes_()
Benutzeravatar
edel
Beiträge: 3667
Registriert: 28.07.2005 12:39
Computerausstattung: GameBoy
Kontaktdaten:

Re: Funktion aus CoreFoundation funktioniert unzuverlässig

Beitrag von edel »

Alle API Funktionen die PB unterstuetzt findest du unter purelibraries\macos

Code: Alles auswählen


CompilerSelect #PB_Compiler_OS
	CompilerCase #PB_OS_Linux
		#APIDIR = #PB_Compiler_Home + "purelibraries/linux/"
	CompilerCase #PB_OS_Windows
		#APIDIR = #PB_Compiler_Home + "purelibraries\windows\"
	CompilerCase #PB_OS_MacOS
		#APIDIR = #PB_Compiler_Home + "purelibraries/macos/"
CompilerEndSelect

Procedure ReadPBApiLib(filename.s)
	Protected *buf.long
	Protected file, size
	Protected pbuf.l
	Protected DLLName.s 
	Protected FunctionsName.s
	
	file = ReadFile(#PB_Any, filename)
	
	If file
		
		size = Lof(file)
		*buf = AllocateMemory(size)
		pbuf = *buf
		
		If Not ReadData(file, *buf, size) = size
			FreeMemory(pbuf) 
			ProcedureReturn 0
		EndIf
		
		CloseFile(file)
		
		If Not *buf\l = 'PURE'
			FreeMemory(pbuf) 
			ProcedureReturn 0
		Else
			*buf + 4
		EndIf
		
		If Not *buf\l = 'EDLL' And Not *buf\l = 'LSO1'
			FreeMemory(pbuf)
			ProcedureReturn 0
		Else
			
			CompilerIf #PB_Compiler_OS = #PB_OS_Windows			
				*buf + 9
			CompilerElse
				*buf + 5
			CompilerEndIf
			
		EndIf
		
		DLLName = PeekS(*buf, #PB_Any, #PB_Ascii)
		
		Debug DLLName
		
		*buf + Len(DLLName) + 1
		
		Repeat			
			FunctionsName = PeekS(*buf, #PB_Any, #PB_Ascii)
			
			Debug "    " + FunctionsName
			
			*buf + Len(FunctionsName) + 3
		Until *buf >= pbuf + size
		
		ProcedureReturn *Lib 
	EndIf
	
EndProcedure

Procedure Main()
	Protected dir = ExamineDirectory(#PB_Any, #APIDIR, "*.*")
	
	If dir
		
		While NextDirectoryEntry(dir)
			
			If DirectoryEntryType(dir) = #PB_DirectoryEntry_File
				ReadPBApiLib(#APIDIR + DirectoryEntryName(dir))
			EndIf
			
		Wend
		
		FinishDirectory(dir)
	EndIf
	
EndProcedure:End Main()
In den ersten 4 Bytes steht ERUP, an Position 9? steht um welche Aufrufkonvention es sich handelt, danach kommt noch ein Eintrag was wohl importiert werden soll (Windows, Linux bzw MacOS), danach kommt noch die Lib bzw der Eintrag fuer den Linker. Ab da stehen dann die einzelnen Funktionen, getrennt durch eine Null,Parameteranzahl und wieder eine Null.

Soviel ich weiss ist die apifunctions.txt nur fuer die Autovervollstaendigung zustaendig.
Benutzeravatar
Shardik
Beiträge: 738
Registriert: 25.01.2005 12:19

Re: Funktion aus CoreFoundation funktioniert unzuverlässig

Beitrag von Shardik »

Hallo edel,

vielen Dank für Dein plattform-übergreifendes Listing zur Ausgabe aller in PB deklarierten API-Funktionen. Jetzt kann sich jeder aus der Ausgabe Deines Programms eine sortierte Liste aller vordefinierten API-Funktionen erstellen.

Hätte ich gestern mit meinem Hex-Editor auch einmal ins purelibraries/macos-Verzeichnis geschaut, dann hätte ich es auch selbst finden können... :wink:
Antworten