Wie man einen BMax-String aus einer C-Funktion zurück gibt

Übersicht BlitzMax, BlitzMax NG FAQs und Tutorials

Neue Antwort erstellen

BtbN

Betreff: Wie man einen BMax-String aus einer C-Funktion zurück gibt

BeitragDi, Jul 31, 2007 10:19
Antworten mit Zitat
Benutzer-Profile anzeigen
Zuerst einmal muss man die blitz.h aus brl.blitz includieren, dies geschieht so:
Code: [AUSKLAPPEN]
#include <brl.mod/blitz.mod/blitz.h>

Das BMK setzt automatisch die Includepfade so, dass dies funktioniert.

Nun unsere Test-Funktion:
Code: [AUSKLAPPEN]
BBString *myCFunction()
{
   char *myCString = "Hallo, das ist ein Test.";
   BBString *myBMaxString = bbStringFromCString(myCString);
   return myBMaxString;
}

Hier wird zunächst eine Funktion mit dem Rückgabetyp BBString* erstellt, was den Strings von BMax entspricht und in blitz_string.h definiert ist.
Die erste Zeile der Funktion sollte klar sein.
In der zweiten Zeile benutze ich die Funktion bbStringFromCString, welche die Funktion ist, die sich hinter String.FromCString() in BMax verbirgt. Sie macht aus unserem CString einen BMax-String, welcher anschließend zurück gegeben wird.

Und hier das zugehörige BMax-Programm zum testen:
Code: [AUSKLAPPEN]
SuperStrict

Framework BRL.Blitz

Import "main.c"

Extern "C"
   Function myCFunction:String()
EndExtern

WriteStdOut(myCFunction()+"~n")

End

Im grunde verlagert man hier nur den Teil, den man sonst in BMax machen würde in den C-Code. Ich finde aber, dass es dort wesentlich besser aufgehoben ist, als im BMax-Code und für mehr übersichtlichkeit sorgt.

Wenn ich rausfinde, wie man Types sicher aus einer C-Funktion heraus zurück gibt, werde ichs hier schreiben.
 

Dreamora

BeitragDi, Jul 31, 2007 10:38
Antworten mit Zitat
Benutzer-Profile anzeigen
BBObject in blitz_object.h

bzw. BBObject *bbObjectNew in der zugehörigen .c File

Grundklasse ist bbObjectClass, die müsstest du dem Super zuweisen des BBObject soferns direkt von Object abgeleitet wär.

Aber es ist immer wieder interessant da rein zu gucken, hab grad festgestellt das Mark dem GC wieder einen 3ten Modus verpasst hat ... diesmal BBGC_AGGRESSIVE (-1), was der wohl macht Wink
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen.

Vertex

BeitragDi, Sep 16, 2008 19:00
Antworten mit Zitat
Benutzer-Profile anzeigen
Gibt es bei folgendem Test Memoryleaks?

test.c
Code: [AUSKLAPPEN]
#include <string.h>
#include <brl.mod/blitz.mod/blitz.h>

struct TInfo {
   BBString *a;
   BBString *b;
   BBString *c;
};

BBINT getABC(struct TInfo *info) {
   char *a = "eins";
   char *b = "zwei";
   char *c = "drei";

   info->a = bbStringFromCString(a);
   info->b = bbStringFromCString(b);
   info->c = bbStringFromCString(c);

   return 123;
}


test.bmx
Code: [AUSKLAPPEN]
SuperStrict

Framework BRL.Blitz
Import "test.c"

Type TInfo
   Field A : String
   Field B : String
   Field C : String
End Type

Extern "C"
   Function getABC:Int(info : Byte Ptr)
End Extern

Global info:TInfo = New TInfo

WriteStdout(getABC(info) + "~n")
WriteStdout(info.A + "~n")
WriteStdout(info.B + "~n")
WriteStdout(info.C + "~n")


Wenn ich info->a != NULL in getABC prüfe, dann kommt FALSE heraus. Schlussfolgerung ist, dass info.A bereits ein gültiger String ist (nur halt mit Länge 0). Wenn ich den jetzt mit info->a = bbStringFromCString(a); überschreibe, existiert der alte, leere String doch noch weiter im Heap-Universum? Wenn ja, wie kann ich den vorher löschen? In Bedacht auf GC wird ein free(info->a) wohl nicht reichen, oder?

mfg olli
vertex.dreamfall.at | GitHub

FOODy

BeitragDi, Sep 16, 2008 19:49
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich würde es mit bbObjectRelease(BBObject* obj) versuchen. (oder direkt das BBRELEASE Makro benutzen)
Sobald es keine Referenzen gibt wird das Objekt von dem GC freigegeben.

Grüße,
FOODy
BlitzMax + MaxGUI, 64-bit Arch Linux: Intel Core² E8500 | 8 GB Ram | GeForce GTX 460 · 1024 MB

Vertex

BeitragDi, Sep 16, 2008 20:04
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke!

BBString ist eine Struct, meinst du, dass es da mit bbObjectRelease geht? Wie stehts mit bbStringClass? Denke, die kann ich an bbObjectRelease übergeben, aber übergibt mir BMax an meine C-Funktion dann auch eine Referenz auf bbStringClass?
vertex.dreamfall.at | GitHub

FOODy

BeitragDi, Sep 16, 2008 20:15
Antworten mit Zitat
Benutzer-Profile anzeigen
Du könntest den BBString einfach zu ein BBObject casten, da die Struktur mehr oder weniger gleich ist, oder direkt das BBRELEASE Makro verwenden, welches auch von bbObjectRelease aufgerufen wird.

String in BlitzMax ist nichts weiter als ein BBString* in C.
Also wird BlitzMax dir eine BBString* Instanz übergeben.

bbStringClass ist eine Instanz die die Stringklasse beschreibt.
(Sie beinhaltet die vtable, Kontruktor/Destruktor, ...)

Grüße,
FOODy
BlitzMax + MaxGUI, 64-bit Arch Linux: Intel Core² E8500 | 8 GB Ram | GeForce GTX 460 · 1024 MB

Vertex

BeitragDi, Sep 16, 2008 22:52
Antworten mit Zitat
Benutzer-Profile anzeigen
OK, ich habe es jetzt:
Man darf nicht zu bbObject casten, und dann mit bbObjectRelease freigeben sondern muss mit if(info->a != NULL) bbStringClass.free(info->a); das ganze erledigen.

Warum?
Code: [AUSKLAPPEN]
static void bbStringFree( BBObject *o ){
   BBString *str=(BBString*)o;
   if( str==&bbEmptyString ){
      str->refs=BBGC_MANYREFS;
      return;
   }
   bbGCMemFree( str,sizeof(BBString)+str->length*sizeof(BBChar) );
}


das ist die free-"Methode" der bbStringClass. Sie prüft nämlich zusätzlich, ob der String == bbEmptyString ist, der nicht vom GC freigegeben werden darf.

Weiß aber nicht 100% ob bbReleaseObject vllt. doch die bbStringFree Funktion indirekt aufruft?!
vertex.dreamfall.at | GitHub
 

porcus

BeitragMi, Sep 17, 2008 13:24
Antworten mit Zitat
Benutzer-Profile anzeigen
Man kann auch einfach mit byte ptr und String.FromCString(blurp) arbeiten um einen String von
nem C Teil in den Bmax Teil zu nehmen.
*Account deaktiviert*

BtbN

BeitragMi, Sep 17, 2008 16:21
Antworten mit Zitat
Benutzer-Profile anzeigen
Was sehr memleak-anfällig ist.

FOODy

BeitragDo, Sep 18, 2008 8:26
Antworten mit Zitat
Benutzer-Profile anzeigen
@Vertex:
Das einzige was du machen musst ist es BBRELEASE aufzurufen.
Sobald eine Instanz keine Referenzen mehr hat wird die vom GC automatisch freigegeben. (Nicht unbedingt sofort)
BBClass erbt von BBGCPool und definiert die free-Funktion (bzw ein Pointer der auf eine free-Funktion zeigt) die von dem GC aufgerufen wird. (also z.b. das bbStringFree oder bbObjectFree)
bbGCFree "markiert" die Instanz, damit die beim nächsten GC aufruf freigegeben wird. (wird von BBRELEASE aufgerufen)
Mit bbGCMemFree wird der Speichern endgültig freigegeben. (wird z.b. von bbStringFree und bbObjectFree aufgerufen, wenn die Instanz keine Null-Instanz repräsentiert)


Grüße,
FOODy
BlitzMax + MaxGUI, 64-bit Arch Linux: Intel Core² E8500 | 8 GB Ram | GeForce GTX 460 · 1024 MB

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG FAQs und Tutorials

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group