Inhalt
Topic:.ReflectionJc.
.
Topic:.ReflectionJc.usage.
Last changed: 2007-09-23
Laut Wikipedia bedeutet Reflection: dass ein Programm Erkenntnisse über seine eigene Struktur gewinnen kann. (Stand 23. Sep. 2007). Die Strukturinformationen sind normalerweise in Maschinencodeabläufe, Einzel-Datenadressen und Labels für Subroutinen übersetzt und damit nicht mehr unmittelbar von außen zugänglich. Die Zugänglichkeit besteht nur, wenn diese im Compilierungsprozess berücksichtigt wird. Ein Zugang von außen mit Angabe der Daten oder Subroutinen per Name (Symbol) erfordert ein aufgesetztes zusätzliches System. Solche symbolischen Zugänge sind erforderlich oder interessant
für einen Zugriff auf alle Daten in einer laufenden Software, ohne diese im Schritt-Test anzuhalten,
für einen Zugriff auf Daten außerhalb eines Compilierungsprozesses für aufgesetzte Funktionalitäten. Beispielsweise können Parameter zur Laufzeit via XML vorgegeben werden und dann mittels symbolischen Zugriff in die vorhandenen Datenstrukturen abgelegt werden.
für interpretative Abarbeitungen. Beispielsweise kann eine Zustandsmaschine projektiert werden. Die Zustandsmaschine muss bestimmte Bedingungen abfragen und Subroutinen aufrufen (Actions). Wenn dies unabhängig vom Compilierungsprozess erfolgen soll, dann muss ein Interpreter des Zustandsmaschinen-Codes per symbolischen Zugriff die entsprechenden Aktionen ausführen.
Die Reflection erlauben diesen symbolischen Zugang ohne zusätzliche Informationen wie Mapfiles und Listings und daraus abgeleitete Zugangsdaten.
Die Reflection-Informationen verbinden interne Strukturen mit symbolischer Zugriffsmöglichkeit aus der Quellcode-Ebene. Um diese Informationen gegenüber der unbeabsichtigten Nutzung zu verbergen, sollen textuelle Anteile gegebenenfalls auch chiffriert werden können.
Topic:.ReflectionJc.usage.java.
Last changed: 2013-12-09
Reflection sind in einigen Programmiersprachen wie Java, C#, Python fester Sprachbestandteil und erlauben dort eine flexible
Programmierung insbesondere bei Nutzung von Klassen über Netzwerkgrenzen oder dynamischer Programmbestandteile. Die Reflections
sind im Java-Standard-Sprachumfang mit den Klassen java.lang.Class
und das Package java.lang.reflect
repräsentiert. Von jedem Object sind die Reflection-Infos zugänglich. Beim Zugriff wird aber der Zugriffsschutz wie beim
Compilieren beachtet. Standardgemäß zugreifbar sind nur public
-Elemente. Das entspricht dem objektorientiertem Ansatz. Elemente, die von außen gelesen oder gesetzt werden sollen, müssen
public
sein. Für einen Zugriff aus rein informatorischen Gründen auf alle Elemente gibt es die Möglichkeit, den private-Zugriff
freizuschalten: Field.setAccessible(...)
.
In Java umfassen die Reflection auch die Aktivierung von Klassen über den Klassenloader und deren Instanziierung. So kann eine Funktionalität in einem Java-Programm rein über externe textuelle Steuerung beeinflusst werden. Eine entsprechende symbolisch benannte Klasse muss lediglich im Klassenpfad (CLASSPATH) auffindbar sein. Sie wird bei Bedarf geladen und kann aus fest programmiertem Code angesprochen werden, wenn sie ein bestimmtes Interface implementiert.
Topic:.ReflectionJc.usage.Cpp.
Last changed: 2007-09-23
Für C/C++ wird hier eine Reflection-Lösung benutzt, die sich an Java anlehnt. Dabei wird nicht die gesamte Funktionalität der Reflections aus Java unterstützt, folgende Teile sind ausgenommen:
Klassenlader-Funktionalitäten (classLoader)
Sicherheitstest-Funktionalitäten (security check)
Strenge private / package private / protected / public - Unterscheidung
Der Klassenlader ist eine typische Eigenschaft der virtuellen Maschine und für C(++)-Anwendungen nicht zutreffend. Die Security-check.Mechanismen sind insbesondere für den Einsatz von Java in unbekannten entfernten Umgebungen (Internet-Applikationen) gedacht und ebenfalls nicht zutreffend. Die strenge Unterscheidung der Zugriffsrechte sind ein Grundkonzept der Kapselung in der Objektorientierung. So ist es in Java zwar möglich, zu erfahren, dass es ein bestimmtes private-Attribute gibt, jedoch der Zugriff darauf wird mit einer Security-Exception beantwortet. Für die C(++)-Anwendung ist diese strenge Kapselung gelockert, in die Verantwortung des Anwendungsprogrammierers gelegt.
Die drei Hauptklassen der Reflections sind:
class:_ClassJc
class:_FieldJc
class:_MethodJc
Topic:.ReflectionJc.usage.reflAccess.
Last changed: 2013-12-09
Die Reflectiondaten sind nur sinnvoll nutzbar im Zusammenhang mit Datenstrukturen. Im Embedded Bereich insbesondere bei kleineren oder älteren Anwendungen ist es häufig üblich, nur globale Variable zu verwenden, die dann im Mapfile auffindbar sind. Für solche Anwendungen ist die Reflectionlösung zu hoch gegriffen.
Wenn die Adresse einer Datenstruktur (C-struct
oder C++-class
) bekannt ist, dann muss zu dieser Struktur auch die Reflection bekannt sein. Dann sind die Elemente der Struktur bekannt
und auswertbar.
Sind Daten strukturiert global im Speicher vorhanden, dann können die Reflection auch außerhalb des Zielsystems (target) also nur beim Zugreifenden bekannt sein, beispielsweise gebildet aus Listing- und Map-File-Informationen. Es muss dann eine Zuordnung geben Adresse im Target - Reflection.
In größeren Embedded-Applikationen werden die Daten häufig beim Hochlauf dynamisch angelegt. Entweder sie werden im Heap allokiert oder es ist eine spezielle Speicherverwaltung eingebaut. Es ist möglich, dass die Speicheradressen vom Ausbau eines Gerätes, von Startparametern oder aus anderen Gründen variieren. Dann ist eine feste Zuordnung Speicheradresse - Reflection nicht mehr möglich.
Es sind zwei Ansätze zur Reflectionzuordnung möglich, die beide praxisbewährt sind:
a) Vollständige Lösung: Jede Datenstruktur enthält Kopfdaten, die an einer einheitlichen Stelle auf die Reflectiondaten referenziert.
Damit ist mit jeder Daten-Instanz die Reflection sofort bekannt. Dieser Ansatz wird in Java verfolgt. Die Reflection ist im
Basis-Object verankert: Object.getClass()
. Diese Lösung ist notwendig, wenn mit abgeleiteten Daten gearbeitet wird.
b) C-Lösung: In den meisten C-Programmen wird nicht mit Basiszeigern gearbeitet. Es ist kein Platz für eine allgemeine Grundstruktur aller Daten. Bei dieser Lösung gibt es lediglich eine feste Zuordnung einer Root-Instanz und deren Reflection. Die Root-Instanz referenziert alle anderen Daten, egal ob dynamisch allokiert oder statisch definiert. Da in den Reflection der Root-Instanz die Typen aller referenzierten Instanzen bekannt sind, sind also die Reflection aller referenzierten Instanzen bekannt. Es gibt damit zwei parallele Bäume: Den Baum der Daten und den Baum der zugehörigen Reflection.
Wenn bei der Lösung b) eine Datenreferenz nicht auf den in den Reflection angegebenen Typ zeigt sondern die referenzierten
Daten einen anderen struct
-Typ haben, dann läuft dieses System an dieser Stelle auseinander. Dann läuft aber auch in der Funktionalität etwas auseinander,
es sei denn die Programmierer geben einen falschen Typ in der Referenz an und gleichen dieses Problem mit einem regelmäßigen
Pointercasting vor Benutzung des Referenzzeigers aus. Für einen solchen Programmierstil sind die Reflection allerdings nicht
geeignet.
Die Lösung a) unterstützt den Zugriff auf Daten, die in der Referenz als Basiszeiger (Interfacezeiger, Basisklasse, super class) angegeben werden und tatsächlich umfassender sind. Die Lösung b) ermöglicht dann nur den Zugriff auf Daten der Basisklasse.
Die Lösung a) ermöglicht den Signifikanztest der Daten, indem Referenztyp und Instanztyp miteinander verglichen wird. Außerdem lassen sich neben den Reflection in die Object-Basisklasse noch weitere Signifikanztests unterbringen. Man kann damit bei versehentlich fehlerhafter Software diese Fehler aufspüren. Das dürfte für die casting-gefährdete C-Programmierung mindestens interessant sein.
Die Lösung b) hat sich allerdings in der Praxis für C-Programmierung mit quasi statischen nichtabgeleiteten Strukturen bewährt. Es sind damit vom Verfasser des Artikels komplexe kommerzielle Anlagen ausgerüstet worden, bei denen Bedienpersonal insbesondere in der Inbetriebsetzungsphase über Reflectionzugriff beispielsweise eine Feinparametrierung durchführt und Daten zwecks Analysen abgreift.
Dennoch ist Lösung a) auch für die C-Programmierung interessant und wichtig. Die Basis-Struktur für C Jc:ObjectJc und ihr C++-Äquivalent Jc:ObjectJcpp unterstützt dieses.
Die Reflection sind für eine Dateninstanz (struct
oder class
) als Instanz von Jc:ClassJc gegeben als Zeiger ClassJc const*
.
Topic:.ReflectionJc.ReflData.
Last changed: 2007-09-23
Die Reflectiondaten sollen im Anwenderprogramm vorliegen und eingebunden werden. Grundsätzlich besteht aber auch die Möglichkeit, die Reflectiondaten außerhalb beispielsweise in einer Datei zu halten. Das ist interessant für den Fall, dass Daten übertragen und gespeichert werden, und mit den Daten die zugehörigen Reflection-Infos. Dabei muss aber beachtet werden, dass die Reflectiondaten selbst verzeigert sind (Klasse zeigt auf ihre Attribut-Informationen, Attribut-Informationen zeigt auf die Klassen entsprechend dem Attributtyp usw.). Die Verzeigerungen sind im Anwenderprogramm vom Linker vergebene Speicheradressen. Diese Verzeigerung muss dann nachvollziehbar und im Zielsystem nachgezogen werden. Dafür sind Vorkehrungen getroffen.
Topic:.ReflectionJc.ReflData.const.
Last changed: 2007-09-23
Grundsätzlich sind die gesamten Reflection-Infos als Konstante ausgeführt. Das bedeutet, dass kein zusätzlicher Code zum Erstellen der Daten, auch nicht beim Hochlauf nötig ist. Wichtiger ist gegebenenfalls noch, dass diese Konstanten sich auch in einem ROM-Bereich befinden können. Das ist wichtig, weil
bei kleinen (preiswerten) Prozessorboards/Prozessoren ist oft wenig RAM vorhanden, aber durchaus ein angemessener ROM-Bereich,
der Code lässt sich von vornherein hardwareseitig schreibgeschützt laden, wichtig für die Sicherheit der Software beispielsweise auch bei Zugriffen nach einem Software-Absturz: Auf die Reflection-Infos kann man sich verlassen, sie sind keinesfalls überschrieben.
Keine doppelte Haltung von Initialisierungsinfos und abgelegten Daten.
Topic:.ReflectionJc.ReflData.header.
Last changed: 2013-12-09
In C ist es teilweise üblich, nur in einem C-File verwendete Daten dort im C-File als Struktur zu definieren. Nur wenn die Daten in mehreren Compilierungseinheiten (C-Files) verwendet werden, werden sie in einem Headerfile definiert.
Es ist aber durchaus angebracht, Datendefinitionen und Programmcode schon aus dokumentarischen und softwarestilistischen Gründen zu trennen. Also Datenstrukturen grundsätzlich in Headerfiles zu definieren - weil sie Datendefinitionen sind und keinen Code erzeugen. Der Sichtbarkeit - private Kapselung für C - ist damit Genüge getan, dass die Strukturen nicht in irgendwelchen globalen Headerfiles definiert werden sondern sehr geordnet in Headerfiles, die nur bestimmte, oder nur ein C-File includiert, wenn sie nur für diese Compilierungseinheit sichtbar sein sollen. Das ist softwarestilistisch Datenpflege.
Die automatische Reflectiongenerierung hat damit dann ein leichteres Vorgehen: Es werden aus allen Headerfiles die Reflection generiert.
Topic:.ReflectionJc.constReflection.
Last changed: 2007-09-23
Die Konstantendefinitionen erfolgen nach folgendem Schema (gilt für manuell erstellte Reflection ebenso wie für die Generierung):
#define protected public //only active inside this compilation unit #define private public // to enable the access to all elements. #include "Jc/ReflectionJc.h" #include "User.h" //The file where the data are defined. //... extern const ClassJc reflection_User_XYZ const struct Reflection_Fields_UserABC_t { ObjectArrayJc head; FieldJc data[2]; } reflection_Fields_UserABC = { CONST_ObjectArrayJc(FieldJc, 2, OBJTYPE_FieldJc, null, &reflection_Fields_UserABC) , { { "intValue" , 0 //nrofArrayElements , REFLECTION_int32 , (4<<kBitPrimitiv_Modifier_reflectJc) //bitModifiers , (int16)((int32)(&((UserABC*)(0x1000))->intValue) - (int32)(UserABC*)0x1000) , 0 //offsetToObjectifcBase , &reflection_UserABC } , { "reference" , 0 //nrofArrayElements , &reflection_UserXYZ , 0 //bitModifiers , (int16)((int32)(&((UserABC*)(0x1000))->reference) - (int32)(UserABC*)0x1000) , 0 //offsetToObjectifcBase , &reflection_UserABC } } }; // const ClassJc reflection_UserABC = { CONST_ObjectJc(OBJTYPE_ClassJc + sizeof(ClassJc) , &reflection_UserABC, null) , "UserABC" , 0 , sizeof(userABC) , (FieldJcArray const*)&reflection_Fields_UserABC , null //method , null //superclass , null //interfaces , 0 };
Das Beispiel definiert die Reflections für eine struct
oder class
mit dem Name UserABC
, die 2 Elemente enthält, darunter eine Referenz auf UserXYZ
. Zunächst werden die FieldJc-Elemente definiert, und zwar als Array mit Kopfdaten. Die Anzahl der Elemente, hier 2, muss
zweimal angegeben werden. Die Angaben der eigenen Adresse &reflection_Fields_UserABC
wird durch das Makro CONST_ObjectArrayJc
passend umgesetzt. Die eigene Adresse steht aus zwei Gründen in den const-Daten:
Einerseits sind damit Signifikanztests der Daten möglich, die die Software auch bei Fehlern in Form von Datenüberschreibern (Querschlägern) sicherer machen.
Andererseits stehen damit die eigenen Adressen an definierter Stelle innerhalb jedes struct:_ObjectJc in den Daten. Das ist wichtig, wenn Daten übertragen werden und die Reflections außerhalb angewendet werden.
Wesentlich ist die Offsetbildung der Daten im 5. Element eines FieldJc
. Im Falle von abgeleiteten C++-Klassen müssen hier zusätzlich static_cast<ObjectJc> erfolgen, da der Offset auf die Position
der Basisklasse ObjectJc innerhalb einer C++-class bezogen ist. Das ist in diesem Beispiel nicht dargestellt. Der Bezug auf
eine fiktive Instanz auf der Adresse 0x1000
ist notwendig (0
wäre intuitiver), da ein GNU-Compiler mit einer Adresse 0
nicht arbeiten möchte.
In der folgenden Definition der konstanten ClassJc
-Instanz ist die Referenz auf die Fields eingetragen. Im Beispiel werden nur Fields verwendet. Der Zugriff auf Methoden und
Superclasses ist vorgesehen.
Die Reflections für die skalaren Basistypen, REFLECTION_char usw., sind in Reflection_Jc.h als Konstante im kleinen Bereich (bis max. 100) definiert und als (Class_Jc const *) umgecastet. Das hat den Vorteil, dass bei ausgelagerten Dateien diese Zeiger problemlos erkannt werden können, ohne diese Reflectiondaten selbst zu haben. Damit kommt ein Datenabbild nur mit seinen eigenen Reflectiondaten aus, wenn davon ausgegangen wird, das ein Datenabbild neben seinen eigenen Strukturen meist nur skalare Basistypen verwendet, und Zeiger auf fremde Typen (Interfaces), die dann aber sowieso nicht im Datenabbild dabei sind.
Für alle anderen Typen muss der Linker die Definition des jeweiligen Types, enthalten in irgendeinem compilierten C-Files wenn ein komplexes System vorliegt, finden.
Topic:.ReflectionJc.genReflection.
Last changed: 2009-09-23
Die Reflection enthalten keine andere Information, als der Compiler aus den Informationen in Headerfiles sie zusammenstellt. Es wäre zusätzliche Mühe, diese Codes mit der Hand schreiben zu müssen. Daher gibt es folgendes Verfahren zur Generierung der .c und .h-Files:
Der Headerfile, der Anwender-Datenstrukturen beschreibt, muss in seiner Syntax den Anforderungen des ZBNF-Scripts Cheader.zbnf entsprechen. Das sind keine wesentlichen Einschränkungen. Wenn ein Headerfile komplexe define-Strukturen enthält, dann ist er gegebenenfalls erst nach dem Präprozessordurchlauf des Compilers syntaktisch fassbar. Das sollte vermieden werden.
Der Inhalt des Headerfiles wird mit einem ZBNF-Parser und der ZBNF-Syntaxbeschreibung geparst, mit einem Java-Programm werden dann die Reflection.c-Files generiert.
Topic:.ReflectionJc.ifcUserData.
Last changed: 2009-09-23
.
Topic:.ReflectionJc.ifcUserData..
Last changed: 2007-09-23
Die zugehörigen Reflection-Informationen zu Anwenderdaten sind auf folgende Weise zu erhalten:
Entweder die Anwenderdaten basieren auf ObjectJc
und enthalten dort den Zeiger auf die Reflection (ClassJc const*
). Die Subroutine getClass_ObjectJc()
liefert die entsprechende Referenz.
Oder es wird von einer übergeordneten Instanz ausgegangen, für die die Reflection in der eben genannten Art vorliegen. Ausgehend
von der übergeordneten Instanz wird eine referenzierte Instanz ermittelt, parallel dazu wird in den Reflection der Typ der
referenzierten Instanz ermittelt. Dann braucht die referenzierte Instanz nicht auf ObjectJc basieren, es kann sich beispielsweise
um eine einfache Datenstruktur handeln. Wenn die Referenz der Instanz von einem Basistyp ist, die Instanz selbst abgeleitet
(C++), dann zeigt der Zeiger im Maschinencode auch auf die Adresse, auf der die Basisdaten stehen. Referenz und Typ passen
also immer zueinander. Man kann aber auf diesen Weg keine Daten der abgeleiteren Klasse sehen. Die aufzurufende Subroutine
dafür ist getClassAndObj_FieldJc(...)
, siehe in folgendem Text.
In beiden Fällen gilt, das falsche Reflection-Daten selbstverständlich falsche Zugriffe nach sich ziehen. Das gilt insbesondere für den zweiten Fall, da hier eine Fehlerfortpflanzung möglich ist. Solche Fälle können auftreten, wenn eine Datenstruktur geändert ist, der Reflectionfile wurde aber nicht neu compiliert. Das ist ein Fehler im Make-Prozess, der auch an anderen Stellen fatal ist und ausgeschlossen werden sollte. Ein Verschreiber des Anwenders (Reflection-Typ verwechselt) ist freilich ähnlich fatal wie eine Verwechslung bei einem cast. In einer ordnungsgemäß compilierten Software ist das Verfahren fehlerfrei.
Topic:.ReflectionJc.ifcUserData..
Last changed: 2007-09-23
Wenn den Name eines Element in der Klasse oder struct
vorgegeben ist, dann kann mit Aufruf von
FieldJc const* field = getDeclaredField_ClassJc (clazz, StringJc* sName);
das benannte Element (Attribut oder Referenz) gesucht werden. Die Suche ist eine Iteration über alle Fields der ClassJc und
dauert eine kurze Zeit. Das Ergebnis ist die FieldJc
-Instanz im const-Bereich. Dieser Zugriff erfolgt nur unter Kenntnis der ClassJc, unabhängig von den Anwenderdaten. In Java
gibt es die adäquate Methode. Auch in Java werden dabei Fields auch mit private
-Kapselung gefunden.
Wenn das erforderliche Element nicht vorhanden ist, dann wird eine Exception NoSuchField
erzeugt. Das ist adäquat Java. Der Anwender sollte also um diese Methoden ein TRY
-CATCH
anordnen, wie es in Kapitel beschrieben ist.
Unter Kenntnis der Instanz FieldJc
können nun die weiteren statischen Eigenschaften des Fields wie Typ, Sichtbarkeit, Modifikatoren getestet werden. immer noch
ohne auf Anwenderdaten zuzugreifen.
Ein Array aller Fields bekommt man mit dem Aufruf von
FieldJcArray const* fields = getDeclaredFields_ClassJc(clazz);
Damit kann über alle Fields iteriert werden. Ein FieldJcArray
basiert auf ObjectArrayJc
, die Anzahl der Fields kann also über fields->head.lenght
ermittelt werden, die einzelnen FieldJc
sind über fields->data[...]
erreichbar.
Topic:.ReflectionJc.ifcUserData..
Last changed: 2007-09-23
Mit den korrekten Reflection-Informationen FieldJc
und dem Zeiger auf die Anwenderdaten kann auf die Attribute der Anwenderinstanz zugegriffen werden. Dabei muss die Referenz
auf die Anwenderdaten auf die Adresse der ObjectJc
-Basisklasse angegeben werden, wenn diese auf ObjectJc
basiert. Damit ist ein static_cast<ObjectJc*>(instance)
notwendig bei gegebener Instanzadresse. Die Methoden für Datenzugriffe von FieldJc
übernehmen einen void-Zeiger, damit werden keinerlei Prüfungen zur Compilezeit ausgeführt. Der void-Zeiger ist aber deshalb
notwendig, weil auch auf Instanzen zugegriffen werden soll, die nicht auf ObjectJc
basieren. Im allgemeinen C/C++-Umfeld kann eine Vererbung von ObjectJc als wesentlichstes Paradigma nicht erzwungen werden,
da mit Fremdcode auch umgegangen werden muss. Der Zwang zur fehlerfreien Programmierung ist der selbe, wie er etwa bei Operationen
wie memcpy
oder C-castings bzw. reinterpret_cast
angewendet werden muss.
Lesen von Werten wie in Java:
int32 getInt_FieldJc(field, obj)
liefert den int-Wert, gegebenfalls gecasted wenn das Element nicht vom int-Typ ist. Diese und die folgenden Methoden sind
gleichartig auch in Java vorhanden.
float getFloat_FieldJc(field, obj)
liefert den float-Wert, gegebenfalls gecasted.
double getDouble_FieldJc(field, obj)
liefert den double-Wert, gegebenfalls gecasted.
bool getBool_FieldJc(field, obj)
liefert den bool-Wert, gegebenfalls gecasted.
int64 getInt64_FieldJc(field, obj)
liefert den int64-Wert, gegebenfalls gecasted.
void* get_FieldJc(field, obj, idx)
liefert die Adresse einer referenzierten Instanz. Dabei wird die Adresse so korrigiert, dass eine vorhandene Basisklasse
ObjectJc innerhalb der Instanz adressiert wird. In C++ ist es möglich, dass verschiedene Basisklassen innerhalb einer Instanz
angeordnet werden. Für die Weiterarbeit mit Reflection muss die Referenz auf ObjectJc innerhalb einer Anwenderinstanz benutzt
werden. Wenn die Anwenderinstanz nicht auf ObjectJc basiert, wird deren unmittelbare Adresse geliefert.
Die letzte Methode enthält einen Index, den es in Java nicht gibt. Ist das Datenelement kein Array, dann muss hier -1 übergegeben werden. Die Nutzung eines solchen Index sollte auch auf die anderen oben genannten Methoden erweitert werden.
Setzen von Werten wie in Java:
void getFloat_FieldJc(field, obj, float)
setzt den float-Wert, gegebenfalls gecasted.
void setDouble_FieldJc(field, obj, double)
setzt den double-Wert, gegebenfalls gecasted.
void setBool_FieldJc(field, obj, bool)
setzt den bool-Wert, gegebenfalls gecasted.
void setInt64_FieldJc(field, obj, int64 )
setzt den int64-Wert, gegebenfalls gecasted.
void set_FieldJc(field, obj, idx)
setzt die Adresse einer referenzierten Instanz. Diese Methode ist derzeit nicht implementiert, da bisher nicht benötigt.
Zugriffe für C/C++-Belange als Erweiterung
Die folgenden Methoden gibt es in dieser Art nicht in Java. Sie sind für die Datenanalyse in C/C++ notwendig:
void* getRefAddr_FieldJc(field, obj, idx)
liefert die Adresse einer referenzierten Instanz. Das Verhalten ist ähnlich wie get_FieldJc(...)
, hier erfolgt aber keine Korrektur der Adresse auf ein ObjectJc
. Die Methode wird einerseits innen benutzt, andererseits dient sie zur Anzeige des tatsächlichen Inhaltes einer Referenz
ohne Korretur für Inspector-Zwecke.
void* getMemoryAddress_FieldJc(field, obj)
liefert die Adresse des Feldes. Diese Methode ist innere Methode und dient zur Speicheradress- und Inhaltsanzeige (Inspector).
ClassJc const* getClassAndObj_FieldJc(field, obj, idx, void** retObj)
liefert Referenz und Typ eines Fields. Diese Methode existiert nicht in Java, da in Java der Typ eines Objektes immer aus
dem Object selbst ermittelt werden kann (Object.getClass
). In den Reflections unter C/C++ ist das aber nicht so, da die Basisklasse Object nicht generell vorausgesetzt werden kann.
Die Typinformation wird aus dem gegebenem FieldJc
gelesen. Die Referenz zeigt auf die Basisklasse ObjectJc
wie get_FieldJc(...)
wenn vorhanden.
Verfahrensweise bei Arrays und Containern
In Java müssen Arrays und Container manuell durchsucht werden. Bei einem Array kann man immer die Länge ermitteln, unabhängig von dessen Typ. Der Elementtyp eines Arrays ist aus der Abfrage der ClassJc des Arrays ermittelbar. Dann kann ein gezielter Zugriff auf die Elemente erfolgen, wie am Beispiel des folgenden Java-Codes gezeigt wird:
int[] testArray = new int[10]; //the users program // //inspect it: Object inspectObj = testArray; //type unknown... Class clazz = inspectObj.getClass(); String clazzName = clazz.getName(); if(clazzName.equals("[I")) { //it is an integer array: int[] inspectInt = (int[])inspectObj; //cast int length = inspectInt.length; inspectInt[length-1] = 333; }
Handelt es sich um ein Array von Referenzen auf eine Klasse, dann wird als Name "[L..."
angegeben. Das L
steht für Object
, danach folgt die Typbezeichnung der Referenzen des Arrays. Das ist lediglich eine Zusatzinformation. Auf die Array-Elemente
muss nun ähnlich dem int[]
-Beispiel zugegriffen werden, wobei die Zielreferenz entweder zum angegebenen Typ passen muss oder Object
ist. Von diesem Object kann dann wieder die tatsächliche getClass()
ermittelt werden, eine abgeleitete Instanz ist möglich.
Handelt es sich um einen Container wie List
dann muss auf den Container entsprechend zugegriffen werden, um danach die Class
der Elemente zu ermitteln.
Dieses Verfahren ist umständlich aber vollständig. In C/C++ ist es deshalb nicht allgemein anwendbar, weil es in C/C++ eine größere Vielfalt von Möglichkeiten der Gestaltung von Arrays gibt. Instanzen in Arrays oder Container sind nicht immer von Object abgeleitet. Es gibt es auch den typischen Fall der embedded Arrays wie
typedef struct MyStruct_t{ int a; float b;}MyStruct; MyStruct array[25];
Hierbei kann ein allgemein programmierter Zugriff nur über sizeof-Kenntnis und Adressrechnung erfolgen, weil ein casting dort nicht erfolgen kann.
Die Vielfalt der Gestaltung von Arrays und Containern wäre nur durch aufwändigere Anwenderprogrammierung als in Java zu lösen,
dabei müssen die Eigenschaften der Arrays jeweils spezifisch aus den Reflection ermittelt werden. Das Verfahren ist auch nicht
Java-kompatibel Daher wurde die Array/Container-Erkennung und deren Auflösung in die Grundfunktionen von FieldJc
eingebaut. Ein Zusatzparameter idx
sorgt für eine entsprechende Indizierung eines Elementes in einem Array oder Container. In den Reflection wird getestet,
ob es sich um ein statisches Array oder um ein embedded Array fester Größe handelt. Dann ist in der jeweiligen Methode die
Adressrechnung intern möglich, da die Feldgröße und Byteanzahl in den Reflection steht. Handelt es sich um ein dynamisches
Array des Grundtyps ObjectArrayJc
dann ist die Größe in dessen Kopfdaten ermittelbar. Auch bestimmte Typen von Containern werden berücksichtigt, wobei die
Container eines UML-Frameworks mit zusätzlich zugelinkten Methoden einbezogen werden können. Die Information über den Containertyp
steht in den Reflection. Die Anwenderprogrammierung ist damit wesentlich vereinfacht. Für den Fall von Object-basierenden
abgeleiteten Klassen kann wie in Java von der Referenz des Array- oder Container-Elementes dessen ClassJc bestimmt werden.
Das wird aber insgesamt von der oben genannten Methode getClassAndObj_FieldJc(...)
ausgeführt, die von get_FieldJc()
intern gerufen wird. Die Indizierung wurde derzeit noch nicht bei den set- und get-Methoden für skalare Werte ausgeführt,
sollte aber als Erweiterung genauso ausgeführt werden. Damit ändern sich die Signaturen der get- und set-Methoden auf skalare
Werte um diesen zusätzlichen Parameter. Ein doppelter Satz von Methoden mit oder ohne Index ist nicht empfehlenswert, da damit
die Anzahl der Methoden zunimmt, andererseits mit dem idx=-1
immer eine Kompatibilität zum nichtindizierten Fall durch einfache Quellenänderung herstellbar ist.
Um solche Funktionalitäten kompatibel auch in Java abzubilden (Javalike-Konzept), ist dort eine entsprechende Klasse als Erweiterung
zu java.lang.reflection.Field
möglich (org.vishia.bridgeC.FieldJc
) , so dass die C-Erweiterungen wieder in Java ähnlich anzutreffen sind.
Topic:.ReflectionJc.accessToUserDataViaReflection.
Last changed: 2007-09-23
Bei den Datenzugriffen wird die Referenz auf die Instanz als Argument angegeben. In C ist auch bei C-like-Interfaces der Zeiger auf die Instanz immer identisch mit dem Zeiger auf die Basisklasse Object_Jc. Bei den Datenzugriffen auf Feldelemente, die selbst nicht auf Object_Jc basieren, sondern nur deren Feld-Kopfstruktur ObjectArrayHead_Jc, ist der Zeiger auf die Instanzdaten nicht auf Object_Jc* konvertierbar. Daher wird bei den Methoden des Zugriffes für C wie
METHOD_C int getInt_Field_Jc(const Field_c* ythis, void* obj);
der Zeiger auf die Instanz in der Form void* übergeben, siehe Abschnitt "Zugriff auf Daten von Arrays ohne Reflectioninfo der einzelnen Elemente"
Bei C++ ist dagegen der Zeiger auf die Instanzdaten meist nicht identisch mit dem Zeiger auf die Basisklasse ObjectJc
. Es wäre eher ein Zufall bzw. es ist nur garantiert bei einfachen Klassen, die nur auf ObjectJc
basieren. Eine Referenz kann vom Typ eines Interfaces auf eine Instanz sein. In diesem Fall zeigt die Referenz auf die Daten
des Interface, beginnend mit dessen virtueller Tabelle inmitten der Instanzdaten, an der das Interface angeordnet ist.
Das nachfolgende Schema zeigt ein Speicherlayout, entnommen dem TestReflection.*
für die Instanz myData
. Für den Aufruf per Interface kennt die aufgerufene Methode, im Bespiel accessViaInterface(MyInterface* refIfc)
die Daten ab der Position refIfc
. Dort steht die virtuelle Tabelle des Interfaces und danach etwaige Daten der Interfaceklasse (wenn es kein reines Interface
ist). Diejenigen Methoden, die in MyData
überladen sind, kennen den Offset zwischen MyData und MyInterfaceBase und korrigieren den this-Zeiger um -8. Das leistet
der C++-Compiler.
myData: 9C 99 43 00 MyData::vtbl DA DA 5E BA :;baseData refIfc: 90 99 43 00 MyInterfaceBase::vtbl 80 99 43 00 ObjectifcBaseJcpp::vtbl 5E BA FC 0E ::significance 0C 3E 33 00 ::significanceAddress 333E18: 00 00 31 02 ObjectJc::objectIdentSize 18 3E 33 00 ::ownAddress CD CD FF FF ::idSyncHandles C0 FA 43 00 ::reflectionClass 70 3E 33 00 MyData::refData
Damit mit Reflection gearbeitet wird, ist die Referenz auf ObjectJc
notwendig. Diese steht zwar kurz dahinter, aber die Position hängt von der Datenkonstellation insgesamt ab. Keine Zeigerarithmetik
kann diese bestimmen, sondern nur der Aufruf der Methode
ObjectJc* obj = refIfc->toObject();
die im Basis-Interface ObjectifcBaseJcpp
von MyInterface
definiert ist und mit
ObjectJc* MyData::toObject(){ return this; }
implementiert ist. Dieses return this
gibt nicht den original übergebenen this-Zeiger zurück, sondern addiert den Offset, um die Basisklasse ObjectJc zu referenzieren,
wie es der return-Typ verlangt, ein implizites cast. Das leistet der C++-Compiler. Mit der Referenz auf die ObjectJc
-Basis können nun reflection-Methoden gerufen werden:
ClassJc const* clazz = getClass_ObjectJc(obj); char const* clazzName = getName_ClassJc(clazz); StringJc fieldName = s0_StringJc("refData"); FieldJc const* field = getDeclaredField_ClassJc(clazz, &fieldName); void* refAddr = getMemoryAddress_FieldJc(field, obj); void* refPoor = getRefAddr_FieldJc(field, obj, -1); void* refObj; ClassJc const* clazzField = getClassAndObj_FieldJc(field, obj, -1, &refObj);
In diesem Beispiel wird eine Referenz auf ein Interface MyInterface
ermittelt, diese Referenz zeigt im Beispiel auf eine Instanz von MyData2. Die drei Zeiger verdeutlichen das C++-typische
Speicherlayout hier von der Instanz von MyData2
:
myData2:E8 99 43 00 MyData2::vtbl DA DA 5E BA :;baseData refPoor:DC 99 43 00 MyInterfaceBase::vtbl 333E74: CC 99 43 00 ObjectifcBaseJcpp::vtbl 5E BA FC 0E ::significance 74 3E 33 00 ::significanceAddress 333E80: 00 00 34 02 ObjectJc::objectIdentSize 80 3E 33 00 ::ownAddress CD CD FF FF ::idSyncHandles 10 FB 43 00 ::reflectionClass 56 34 12 A0 MyData2::value
MyData2 hat im Beispiel ein ähnliches Speicherlayout. Die refAddr
aus den obigen Anweisungen ist diejenige, auf der die Referenz steht. Es ist der Wert0x333E28
der im oberen Speicherlayout zu finden ist. Dort steht die Referenz mit dem Wert 0x333E70
, in refPoor
gespeichert. Um von dieser Adresse ausgehend weiterhin mit Reflections zu arbeiten, muss man irgendwie geeignet die Adresse
des ObjectJc
-Anteils der Instanz zeigern. Es ist allerdings so, dass im Umfeld des C++-compilierten Codes der Typ der Referenz nicht bekannt
ist. Es handelt sich um ein void*
, der durch Lesen der Referenz ermittelt wird. Der Typ steht allerding in der zuständigen FieldJc
-Instanz, hier field
, und zwar im Typ des Fields. Dieser ist reflection_MyInterface
. Für diesen Typ ist bekannt, dass er auf ObjectifcBaseJcpp
basiert, entsprechend der Notation im Headerfile. In den ClassJc
-Daten für reflection_MyInterface
ist sowohl das entsprechende Bit in modifiers
gesetzt, als auch das Datenelement posObjectBase
ist gesetzt mit dem Wert 0x0004. Der Wert ergibt sich bei der Compilierung der generierten Reflection aus dem Ausdruck
(int)(static_cast<ObjectifcBaseJcpp*>((MyInterface*)0x1000)) - 0x1000
Der Ausdruck wird vom Compiler als Konstante berechnet mit den gleichen Bedingungen, wie anderer Code compiliert wird.
Mit diesen Informationen kann nun eine Adresskorrektur des void*
-Zeigers der Referenz um 4 und ein nachfolgendes cast auf den Typ ObjectIfcBaseJcpp
erfolgen. Die Korrektur und cast-Aktion wird innerhalb der Routine getClassAndObj_FieldJc(...)
ausgeführt:
ObjectifcBaseJcpp* objifc = (ObjectifcBaseJcpp*) ((MemUnit*)(ref) + offsetBase);
Eine Adresskorrektur und ein hartes cast ist allerdings eine Vermutung, dass alle Daten richtig sind. Wenn im Anwenderprogramm ein Fehler vorliegt, dann würde der nachfolgende Aufruf
retObjBase = objifc->toObject();
zu einem fatalem Absturz führen, da der Maschinencode über den Speicherinhalt die virtuelle Tabelle aufsucht und dort einen
indirekten Call ausführt. Im Speicher kann im Grunde genommen irgend etwas stehen, erzeugt durch gegebenenfalls einen Anwenderfehler.
Ein durchaus typischer anderer Anwender-Fehler ist, dass die Compilierung der Reflection-Information möglicherweise nicht
aktuell ist, da das Make-System nicht korrekt arbeitet. Daher ist vor dem Aufruf ein Sicherheitscheck eingebaut, der kaum
Rechenzeit benötigt aber den letzteren Fehler entdeckt und Datenfehler mit einer höhereren Wahrscheinlichkeit entdeckt: Im
ObjectIfcBaseJcpp
sind zwei Datenzellen enthalten, die einerseits eine signifikante Belegung 0xefcba5e
und andererseits die eigene Speicheradresse enthalten. Das ist im obigen Memory-Layout erkennbar. Bei dem Signifikanz-Wert
kann man ifcbase
lesen, wenn man das e
als i
und die 5
als s
liest. Das ist im Debugmodus eine kleine Merkhilfe. Die Wahrscheinlichkeit, dass bei einem Datenfehler diese 2 Belegungen
korrekt sind, aber die vtbl-Adresse falsch, ist mindestens 1 : 3.
Nach diesem Signifkanz-Check kann nun objifc->toObject()
gerufen werden und damit über die korrekte Implementierung dieser Methode in der instanziierten Klasse der ObjectJc
-Zeiger ermittelt werden.
Wenn eine Referenz vorliegt von einen Typ, der auf ObjectJc
selbst basiert, dann ist das Verfahren adäquat. Das entsprechende Bit in den ClassJc
des Referenztyps ist gesetzt, und der Offset zu ObjectJc
ist bekannt, beispielsweise für den Typ MyData
mit
(int)(static_cast<ObjectJc*>((MyData*)0x1000)) - 0x1000
niedergelegt. Ein Signifikanztest ist auch hier möglich, weil in einem ObjectJc
im Datenlement ownAddress
immer die selbe Speicheradresse stehen soll, auf der ObjectJc
liegt. Dieser Signifikanztest ist derzeit nicht aktiv, weil diese Festlegung ggf. nicht in allen Produktiv-Codes derzeit
beachtet wird (TODO). Es ist allerdings auch hier nicht so kritisch, da keine Methode gerufen wird sondern im Fehlerfall lediglich
ein falscher Zeiger auf ClassJc
ermittelt wird. Dieser ist einerseits auch signifikanz-testbar, andererseits gibt es dann falsche Anzeigen, die von der Anwendung
bemerkt werden. Der scharfe Signifikanztest sollte hier per Compileroption abschaltbar sein wo nötig und ansonsten erfolgen
(TODO).
Topic:.ReflectionJc.accessToMethod.
Last changed: 2007-09-23
Der Zugriff auf Methoden in Reflection ist derzeit nicht aktiv genutzt und getestet. Die Vor-Überlegungen und -Untersuchungen und vorhandene Codes sollen allerdings hier dargestellt werden.
Die relevante Struktur ist struct:_MethodJc, der Zeiger auf ein Array von methoden in ist struct:_ClassJc als
MethodJcARRAY const* methods;
enthalten. Allerdings werden Methoden bei der automatischen Reflection-Generierung aus Headerfiles derzeit nicht unterstützt.
Die Methoden sind in MethodJc
aufgeführt als
Object__VoidMethod adress;
Das ist die Startadresse. Derzeit nicht ausreichend berücksichtigt sind rein abstrakte virtuelle Methoden von Interfaces,
insbesondere nicht Methoden eines C-like-Interfaces über eine Mtbl
(Methodentabelle).
Die Startadressse ist zwecks einheitlicher Speicherung auf den dargestellten Zeiger auf eine void-Methode gecastet, in C++ mit
typedef void(ObjectJc::*Object__VoidMethod)();
definiert, für C mit
typedef void (*Object__VoidMethod)();
Die Parameterabhängigkeit ist etwas vereinfacht aufgeführt, und zwar mit einem
Type_MethodJc eType;
Die zugehörige enum-Definition
typedef enum Type_MethodJc_t { kNothing_Method , kInt_void, kInt_Int, kInt_2Int, kInt_3Int, kInt_Float, kInt_2Float , kFloat_void, kFloat_Int, kFloat_2Int, kFloat_3Int , kFloat_Float, kFloat_2Float , kVoid_void, kVoid_Int, kVoid_2Int, kVoid_3Int, kVoid_Float, kVoid_2Float }Type_MethodJc;
berücksichtigt typische Konstellationen, aber nicht alle. Der Gedanke hierbei ist: Methoden über Reflection sind nur dann zweckmäßig, wenn es einfache von außen aufrufbare Methoden sind. Diese dürften kaum referenzierte Daten benötigen, sondern eine Kombination von skalaren Werten. Die Kombinationen sind aber nicht hinreichend. Hier kann eine bessere Auswahlmöglichkeit für zukünftige Entwicklungen zweckdienlich sein. Erste Erfolge sind mit dem hier vorgestelltem System jedenfalls möglich.
Die entscheidende Methode für den Aufruf ist adäquat zu Java
invoke_v_MethodJc(const MethodJc* ythis, void* obj, int32ARRAY* params);
Die Parameter sind hier wieder auf eine einfache Art übergeben, ein Ausbau ähnlich wie in Java wäre denkbar. Der Zeiger auf
die Anwender-Instanz wird als void*
übergeben, weil auch hier nicht vorausgesetzt wird, dass alle Instanzen auf ObjectJc
basieren. Wie bei den FieldJc
-Zugriffen ist der Anwender für die Korrektheit des Zeigers verantwortlich bzw. Suchfunktionen sorgen für eine entsprechende
Korrektur aufgrund der gegebenen Reflectiondaten ähnlich wie bei getClassAndObj_FieldJc(..)
.
Der Aufruf invoke_v_MethodJc(...)
ist in C ein einfacher Aufruf über einen Funktionszeiger. In C++ muss die Instanz mit übergeben werden. An dieser Stelle
ist noch Klärungsbedarf (TODO).
Topic:.ReflectionJc.accessToIfc.
Last changed: 2007-09-23
Der Zugriff auf Interfaces und Basisklasse in Reflection ist derzeit aktiv genutzt für den Aufruf von Methoden über das C-Interface, für Datenzugriffe aber derzeit niht genutzt und getestet.
Der Zeiger auf ein Array von Interfaces in ist struct:_ClassJc als
struct ClassOffset_idxMtblJcARRAY_t const* superClasses; struct ClassOffset_idxMtblJcARRAY_t const* interfaces;
enthalten. Sowohl Interfaces als auch Basisklassen werden als Array gefürt. Javalike müsste es nur eine Basisklasse geben, das ist aber in einigen C++-Anwendungen nicht so. Daher wurde auch hier auf ein Array orientiert. Diese Arrays werden bei der automatischen Reflection-Generierung aus Headerfiles derzeit nicht unterstützt, sind allerdings in einigen manuell erstellen Reflection getestet.
Der Typ ClassOffset_idxMtblJc
, auf dem dem Array-Typ basiert, ist wie folgt definiert:
typedef struct ClassOffset_idxMtblJc_t { /** The reflection definition*/ ClassJc const* clazz; /** Index of the virtual table inside its parent.*/ int idxMtbl; }ClassOffset_idxMtblJc;
Der zweite Parameter dieser Struktur ist entscheidend für das dynamische Binden in C. Dieses läuft insbesondere über die Reflection-Daten und ist gesondert in Topic:_DynamicCallInC dargestellt.
Topic:.ReflectionJc.oldoldold.
Last changed: 2007-09-23
In Java sind alle Feldelemente, die keine einfache skalare Variable darstellen (int, float, ...), grundsätzlich über Referenzen geführt. Die referenzierten Instanzen erben von Object und sind demzufolge mit Reflections zugänglich. Beispiel:
final class Data { int a; float f; } ... Data[] dataArray = new Data[12];
In dem gezeigtem Beispiel wird nicht etwa, wie in C(++) zu erwarten, ein Feld mit 12 Elementen vom Typ Data angelegt, sondern es wird nur ein Feld mit 12 nichtinitialisierten Referenzen angelegt. Würde Data nicht final sein, so könnten dort auch von Data abgeleitete Klassen referenziert werden. Um die Feldelemente tatsächlich anzulegen, ist nochmal Arbeit erforderlich:
for(int i = 0; i < dataArray.length(); i++){ dataArray[i] = new Data(); }
Erst damit bekommt man das in C erwartete Ergebnis. Java ist hier etwas komplizierter, aber dafür universell und sicher. Das entspricht dem Referenzkonzept, Java kennt keine "eingebetteten Daten", in C(++) sind eingebetteten Daten dagegen oft erwünscht und durchaus oppurtun. Ein Feld aus zusammengesetzten Elementen soll direkt angelegt werden:
typedef struct Data_t { int a; float f; }Data; Data* dataArray = new Data[12]; //(C++) Data* dataArray = (Data*)(malloc(12*sizeof(Data)); //C-Variante
Dieses einfache und übliche Konstrukt aus C kennt jedoch weder eine Basisklasse Object, damit keine Reflection, noch ist eine Information über die Anzahl der Feldelemente direkt mit dem Feld verbunden vorhanden (muss geeignet extra programmiert werden).
Basisklasse ObjectArrayHead_Jc ist zu verwenden
Aus obigen Grund ist in der CRuntime_Javalike eine Basisklasse ObjectArrayHead_Jc definiert. Diese enthält die Kopfdaten eines beliebigen Feldes und ist von Object_Jc abgeleitet. Es ist möglich, dass die Feldelemente unmittelbar nach den Kopfdaten folgen.Dann bekommt man eine ähnlich kompakte Datenstruktur wie man es von C aus gewöhnt ist. Auf dieser Basis arbeitet das Reflectionprinzip für Arrays. Beispiel:
typedef struct Data_t { int a; float f; }Data; typedef struct DataArray_t { ObjectArrayHead_Jc array; Data data[100]; //NOTE: 100 is only a debug size, use dynamic size, see sizeof_DataArray. }DataArray; /*Constructor sets default values at the elements and set the head data of array.*/ DataArray* constructor_DataArray(DataArray* ythis, int size); #define sizeof_DataArray(SIZE) (sizeof(ObjectArrayHead_Jc) + SIZE * sizeof(Data)) #define new_DataArray(SIZE) constructor_DataArray( (DataArray*)malloc(sizeof_DataArray(SIZE)), SIZE )) DataArray* dataArray = new_DataArray(12);
Im Speicher werden die Kopfdaten und die angegebene Anzahl von Feldelementen des Typs Data in einem Block hintereinander angeordnet. Das ist die Basis für Reflections auf Arrays.
In C: Die Reflections des Arraytypes enthalten die Informationen der Elemente In Java enthält die Reflectioninformation (Class) einer Feldinstanz lediglich den Namen des Feldes, keine weiteren Informationen. Auch das Attribut length, Bestandteil jeder Arrayinstanz, wird in den Reflections nicht angezeigt. Es ist selbstverständlich.
final class Data { int a; float f; } ... Data[] dataArray = new Data[12]; for(int i = 0; i < dataArray.length(); i++){ dataArray[i] = new Data(); } Class classDataArray = dataArray.getClass(); Class classData = dataArray[0].getClass(); System.out.println(classDataArray.getName()); Field[] fieldsDataArray = classDataArray.getDeclaredFields(); System.out.println(classData.getName()); Field[] fieldsData = classData.getDeclaredFields(); Field field_a = classData.getField("a");
Die erste Ausgabe für classDataArray.getName() liefert "[Lpackage.Data" als Anzeige, das es sich um ein Feld vom Referenztyp Data handelt. Das fieldsDataArray ist ein Feld der Länge 0. Die zweite Ausgabe für classData.getName() liefert "package.Data" als Typ des Feldelementes, das fieldsData enthält die Attribute von Data.
In C(++) ist für ein mit ObjectArrayHead_Jc gebautes Feld keine Reflection für die Elemente abrufbar, statt dessen ist beides kombiniert mit
Class_Jc* classDataArray = getClass_Object_Jc(&dataArray->array.object); Field_Jca* fieldsDataArray = getDeclaredFields(classDataArray); Field_Jc field_a = getField_Class(classDataArray, const_String("a")); println_PrintStream(&System.out, getName_Class_Jc(classDataArray);
abrufbar. Die Ausgabe liefert hier wie in Java "[LData", aber fieldsDataArray enthält die Attribute des Feldelementes. Das ist möglich, da die Elemente mit genau diesem Datentyp (und im Gegensatz zu Java nicht mit einem möglicherweise abgeleitetem Datentyp oder mit null) besetzt sind.
Probleme beim Test der Gültigkeit des angegebenen Feldelementes In Java wird ein Wert eines Attributes gelesen oder gesetzt mit
Field field_a = dataArray[0].getClass().getField("a"); int a = field_a.getInt(dataArray[5]); field_a.setInt(dataArray[5], 123);
Das field_a ist dabei aus der Reflection eines Feldelementes bestimmt, aber nicht notwendigerweise aus dem des 5. Feldelementes, sondern beispielsweise aus dem ersten, da alle Elemente vom Aufbau her identisch sind. Grundsätzlich gilt in Java, dass beim Zugriff auf ein Element getestet wird, ob die angegebene Instanz dem selben Typ entspricht wie der class-Typ, der dem Field entspricht (ermittelbar auch manuell programmiert mit field_a.getDeclaringClass(). Nur so kann gesichert werden, dass keine unpassenden Instanzen beim Feldzugriff angegeben werden. Der Aufwand zur Runtime ist ähnlich kritisch/unkritisch zu bewerten wie die Tatsache in Java, dass jeder Index eines Feldes zur Runtime getestet wird. Die VM optimiert hier einiges, es handelt sich jeweils nur im Nanosekunden bei den üblichen Prozessoren.
In C(++) stehen beim adäquaten Aufruf
Field_Jc* field_a = getField_Class_Jc(getClass_Object_Jc(dataArray),const_String_Jc("a")); int a = getInt_Field_Jc(field_a, dataArray[5]); setInt_Field_Jc(field_a, dataArray[5], 123);
die Reflection-Infos aus dataArray[i] nicht zur Verfügung, da ein Feldelement nicht auf Object basiert. Daher muss in diesem Fall der Test der Zulässigkeit des Zugriffes entfallen. Das entspricht aber dem allgemeinem Programmierparadigma in C(++). Es werden an vielen Stellen Zeiger verwendet, ohne nochmaligen expliziten Zulässigkeitstest.
Die Zulässigkeit kann per manueller Programmierung aber wie folgt getestet werden:
if(getDeclaringClass_Field_Jc(field_a) == getClass_Object_Jc(dataArray)) {...}
Das kann in Java ebenfalls genauso explizit erfolgen. Basis für den Test ist hier das Feld selbst, in Java steht an dieser Stelle adäquat wie oben bei der Ermittlung von field_a das Feldelement:
if(field_a.getDeclaringClass() == dataArray[5].getClass()) {...}
Topic:.ReflectionJc..
Last changed: 2007-09-23
Ablauf des Aufrufes von Methoden
Liste aller Methoden über getMethods_Class_Jc()
Suche einer Methode nach Namen und Parametertypen - getMethod(Name, Parameter)
Nichtbeachtung der Funktionsparameter - im Gegensatz zu Java
Kürzel der Funktionsparameter bei C++
Beschränkung auf einfache Methodenparameter
Aufruf von C-Methoden
Aufruf von C++-Klassenmethoden
Nutzung der Adress- und Typinformation für Methodenaufrufe anderer Art
Ermittlung der Zugehörigkeit von Basistypen und Interfaces mit instanceof_Class_Jc(Object, Class)
Nachfolgende Dokumentation ist direkt aus den Headerfile-Kommentierungen
in Reflection_Jc.h generiert, daher in englisch:
UML=/Package[ReflectionJc_h]/Namespace.ownedElement[]/Class[ClassJc]
Class ClassJc im Package ReflectionJc_h
UML=/Package[ReflectionJc_h]/Namespace.ownedElement[]/Class[ClassJc]
+-------'-------'-------'-------'-------'-------'-------'-------+
| object |
+-------'-------'-------'-------'-------'-------'-------'--...32+
| name |
+-------'-------'-------'-------+-------'-------'-------'-------+
| posObjectBase | nSize |
+-------'-------'-------'-------+-------'-------'-------'-------+
| attributes | methods |
+-------'-------'-------'-------+-------'-------'-------'-------+
| superClasses | interfaces |
+-------'-------'-------'-------+-------'-------'-------'-------+
| modifiers | mtbl |
+-------'-------'-------'-------'-------'-------'-------'-------
The typename. If it is a Class represents a primitive type, the name is such as "int", "float", "boolean".
position of the base structure/class ObjectJc inside this type, it is the base address for the offset of fields.
sizeof the type. Hint: It may be longer as 64 kByte, int32 is necessary.
The superclass, ObjectJc if no other superclass.
Array of interfaces to this class.
Some bits determines the kind of the Class, see Modifier_reflectJc
Pointer to jump table for dynamic calls (virtual methods). This is a typed struct, starting with Mtbl_ObjectJc.
Array contains the number of byte which were used if the scalar types with designation 0..0x17 are stored in a byte structure.
see see javaSrc_vishiaBase/org.vishia.reflect.Java2C.nrofBytesScalarTypes.
initializes a ClassJc, see [[ctorc_ClassJc(...)]].
rawMem: MemC - raw memory area, it may be uninitialized. The size may be greater as necessary. The constructor initializes only its own area.
returns: ClassJc -
throws - IllegalArgumentException if the sizeof rawMem is to less.
Array contains the number of byte which were used if the scalar types with designation 0..0x17 are stored in a byte structure.
see see javaSrc_vishiaBase/org.vishia.reflect.Java2C.nrofBytesScalarTypes.
initializes a ClassJc.
All content is set to 0.
returns: void -
Array contains the number of byte which were used if the scalar types with designation 0..0x17 are stored in a byte structure.
see see javaSrc_vishiaBase/org.vishia.reflect.Java2C.nrofBytesScalarTypes.
OBJ: -
returns: -
Array contains the number of byte which were used if the scalar types with designation 0..0x17 are stored in a byte structure.
see see javaSrc_vishiaBase/org.vishia.reflect.Java2C.nrofBytesScalarTypes.
Methods from Class
returns: FieldJcArray -
Array contains the number of byte which were used if the scalar types with designation 0..0x17 are stored in a byte structure.
see see javaSrc_vishiaBase/org.vishia.reflect.Java2C.nrofBytesScalarTypes.
sName: StringJc -
returns: FieldJc -
Array contains the number of byte which were used if the scalar types with designation 0..0x17 are stored in a byte structure.
see see javaSrc_vishiaBase/org.vishia.reflect.Java2C.nrofBytesScalarTypes.
returns: -
Array contains the number of byte which were used if the scalar types with designation 0..0x17 are stored in a byte structure.
see see javaSrc_vishiaBase/org.vishia.reflect.Java2C.nrofBytesScalarTypes.
sName: char -
returns: MethodJc -
Array contains the number of byte which were used if the scalar types with designation 0..0x17 are stored in a byte structure.
see see javaSrc_vishiaBase/org.vishia.reflect.Java2C.nrofBytesScalarTypes.
returns: ClassJc -
Array contains the number of byte which were used if the scalar types with designation 0..0x17 are stored in a byte structure.
see see javaSrc_vishiaBase/org.vishia.reflect.Java2C.nrofBytesScalarTypes.
gets the Name of the class. It is a static method, because the argument class may be a constant for simple types.
clazz: ClassJc -
returns: char -
param - class Either the class object or a constant to design simple types, see REFLECTION_xxx.
Array contains the number of byte which were used if the scalar types with designation 0..0x17 are stored in a byte structure.
see see javaSrc_vishiaBase/org.vishia.reflect.Java2C.nrofBytesScalarTypes.
returns: ClassJc -
Array contains the number of byte which were used if the scalar types with designation 0..0x17 are stored in a byte structure.
see see javaSrc_vishiaBase/org.vishia.reflect.Java2C.nrofBytesScalarTypes.
gets the modifiers for this class or interface, encoded in an integer.
They should be decoded using the methods of class ModifierJc.
returns: int32 -
Array contains the number of byte which were used if the scalar types with designation 0..0x17 are stored in a byte structure.
see see javaSrc_vishiaBase/org.vishia.reflect.Java2C.nrofBytesScalarTypes.
returns true if the type is a primitive Type, like java Class::isPrimitive()
returns: bool -
Array contains the number of byte which were used if the scalar types with designation 0..0x17 are stored in a byte structure.
see see javaSrc_vishiaBase/org.vishia.reflect.Java2C.nrofBytesScalarTypes.
returns true if the type is a reference Type. Not javalike.
THIS: -
returns: -
Array contains the number of byte which were used if the scalar types with designation 0..0x17 are stored in a byte structure.
see see javaSrc_vishiaBase/org.vishia.reflect.Java2C.nrofBytesScalarTypes.
returns true if the type is a instance of a C-struct, based on ObjectJc.
This method is defined outside java, in java all classes based only on Object.
THIS: -
returns: -
Array contains the number of byte which were used if the scalar types with designation 0..0x17 are stored in a byte structure.
see see javaSrc_vishiaBase/org.vishia.reflect.Java2C.nrofBytesScalarTypes.
returns true if the type is a instance of a C++-class, based on ObjectifcBaseJcpp.
It may be also a reference to a interface. The reference type should based on ObjectifcBaseJcpp. This method is defined outside java, in java all classes based only on Object.
THIS: -
returns: -
CONST-Initializer sind Makros für C-Konstanten, sie sind in Headerfiles definiert. C-Konstante sind Konstrukte in { ... } mit ausschließlich konstanten Werten. Die Makros der CONST-Initializer übernehmen Argumente, die zur Compilezeit die Konstanten bestimmen. Die Initializer sind deshalb als Makros definiert, weil die Struktur der Konstanten exakt der struct-Definition folgen muss, die struct ist im Headerfile definiert, daher auch dazu passend diese Makros. Mit denCONST-Intializer ist es auf einfache Weise möglich, C-struct-Daten (Plain Old Data) zu initialisieren. Für Klassen (C++) ist dieses Konzept nicht geeignet.
Macro for constant value of a ClassJc inside a ReflectionImage-structure. The macro REFLECTION_IMAGE should be defined with the identifier of the reflection image.
SNAME -
NAME -
Adaequate complex reflection for C++-classes
SNAME -
NAME -
OWNADDRESS -
Macro for constant value of the ObjectJc on head of any reflectionImage-structure. The macro REFLECTION_IMAGE should be defined with the identifier of the reflection image. Therefore all information to build the constant value is given, no additionaly arguments are needed.
Macro for constant value of a only-data-ClassJc inside a ReflectionImage-structure. The macro REFLECTION_IMAGE should be defined with the identifier of the reflection image.
SNAME -
NAME -
Macro for constant value of a ClassJc inside a ReflectionImage-structure. The macro REFLECTION_IMAGE should be defined with the identifier of the reflection image.
SNAME -
NAME -
Constant Definition of a ClassJc-instance usefull for simple plain old data without special defined methods. A superclass ObjectJc is not specified. It doesn#t mean that the data can't base on ObjectJc, but the access is not able via this reflection definition. It may or may not based on any superclass. Use the macro CONST_xxx_ClassJc instead if you have complexer structures.
It is been designated for a whole reflection constant definition block with the following rules:
The name of the constant whole reflection instance should be reflectionNAME
.
The virtual table is denoted with vtbl
.
The attribute-block is denoted with fields
.
A superclass or any interfaces are not present.
Methods are not present.
SNAME -
NAME -
UML=/Package[ReflectionJc_h]/Namespace.ownedElement[]/Class[FieldJc]
Class FieldJc im Package ReflectionJc_h
UML=/Package[ReflectionJc_h]/Namespace.ownedElement[]/Class[FieldJc]
A field is one entry in the reflection information about attributes or references of any type. In opposite to orignal-Java a FieldJc is not based on Object, but the Field[]-type, in Jc named "FieldJcArray" is based on ObjectJc like every ARRAYJc. It means at ex you cannot call toString_ObjectJc(myField.object), it results in a compiler syntax error. The reason if the FieldJc-type do not based on ObjectJc is: preserve of expenditure, it is not necessary. A field may describe:
a simle scalar attribute of type such as int or long, the type field references to ReflectionintJc
and so on.
a reference to any other type, the instance may be derived also, the type field references to ReflectionReferenceType
.
a embedded other type. That is a possibility only in C(++), not possible in original Java.
but the Java2C translator produces such constructs because optimization, and a hand write code
can use this because optimization. The type field references to ;;ReflectionEmbeddedType,
but the modifier-bit mEmbedded_Modifier_reflectJc is set in bitModifiers.
+-------'-------'-------'-------'-------'-------'-------'--...30+
| name |
+-------'-------'-------'-------'-------'-------'-------'-------+
| nrofArrayElementsOrBitfield_ |
+-------'-------'-------'-------+-------'-------'-------'-------+
| type_ | bitModifiers |
+-------'-------+-------'-------+-------'-------'-------'-------+
| position |offsetToObjectifcBase| declaringClass |
+-------'-------'-------'-------'-------'-------'-------'-------
The symbolic name of the field
Size of the field or size of 1 element if it is an static array.
The class object representing the type of the field. It may be a class object also for primitive types or for primitive Type there is a simple constant value, see REFLECTION_type above.
Don't use this element directly. Only with is getter: getType_FieldJc(...)
The modifiers of the Field. The Bits are defined in Modifier_reflectJc. The concept follows Java, see java.lang.reflect.Field.getModifier or java.lang.reflect.Modifier, but it is enhanced in respect to C/C++ and UML requirements.
position of the field inside a object of the type of the declaring class. The position is the offset from the ObjectJc base class to the field, not the offset from the total base. Because it is possible that the object is known via interface reference. A interface reference pointered the position of the pointer to the virtual table of the interface, a call of obj->toObjectJc() is necessary to get the base for this offset.
Offset in a pointered class to the ObjectifcBaseJcpp class structure if such base interface exists. This value is 0 if it is not a pointer or if it is a pointer of not Object-derivated structures.
The class object representing the class or interface that declares the field represented by this Field object.
SNAME: -
NAME: -
TYPE: -
MODI: -
returns: -
SNAME: -
NAME: -
TYPE: -
returns: -
THIS: -
returns: -
initializes a FieldJc, see ctorc_FieldJc(...).
rawMem: MemC - raw memory area, it may be uninitialized. The size may be greater as necessary. The constructor initializes only its own area.
returns: FieldJc -
throws - IllegalArgumentException if the sizeof rawMem is to less.
initializes a FieldJc. All content is set to 0.
returns: void -
returns: -
THIS: -
returns: -
THIS: -
returns: -
THIS: -
returns: -
Gets the absolute adress of the element represented by this field inside the given Instance. It is assumed, that the instance matches to the Field ythis, it means, the Field ythis is getted from a instance of exactly this type or from the instance itself. This is tested by original Java - set- or get- operations. But it is not tested here to optimize calculation time. If it is a part of a Java2C-translation, the test should be done on Java-level, if it is a directly programmed in C or C++ part, the user should be programmed carefully, how it is ordinary in C or C++.
Simple field, also if the field is a reference type: intance-->[ ...some fields] [ ... ] [ this field----]<--<<This reference will be returned. [ ... ]
Embedded-array-field, also if the field-elements are a reference types: intance-->[ ...some fields ] [ ... ] [ [this field is] ] [ [an aarry ....] ] [ [..element<---]-]--<<This reference will be returned. [ [..element ] ] [ ... ]
If the field references an array, the address of the field itself is returned.
instance: MemSegmJc - the Object. It need not derivated from ObjectJc, it may be any struct or class, but the type should matched to the ClassJc description getted with getDeclaringClass_FieldJc(ythis).
bFieldAddr: bool - If it is true, then instance contains the address of the field already. This method is then used only to calculate the address of an element inside the array, if it this is an array-kind-element. This functionality is used internally.
sVaargs: char - The method can have one or more indices to index an element in the array, if ythis is an array-field. The sVaarg-string contains one or more characters "I" to designate that the following variable arguments are from type int. This concept of processing a variable argument list is established with the Java2C-translator. In Java the type of the elements of a variable argument list are well known in Runtime, other than its usual in C. This String defines the types. It the type is null or empty, no variable arguments are given.
vaargs: va_list - indices for indexing an array element.
returns: MemSegmJc - The address of the field or the address of a element inside the array-kind-field with the given indices. Note: To get the address of elements of a container field, use >getAddrElement_FieldJc(...)
Gets the absolute adress of the container represented by this field inside obj. It is assumed that the obj represented that object, which contains really this field. Otherwise the behavior is undefined.
At example: If a field references an int[]-Array (at ex int32Array-Typ in ObjectJc.h), this method returns the address of the whole array instance.
The container contains the reference. The container may be referenced too. A simplest container is a simple reference, than the container is embedded. A more complex container may be an ObjectArrayJc, or some UML-Containers. It may be embedded or not.
Variant if the container is referenced: intance-->[ ...some fields] [ ... ] [ this field----]--+-->[container....] [ ... ] | [ refOfData--]-->[the data]
+--<<This reference will be returned.
Variant if the container is embedded in the intstance: intance-->[ ...some fields ] [ ... ]
+---->[ [this field is] ]
[ [a container..] ]
[ [refOfData----]-]-->[the data]
[ ... ]
+--<<This reference will be returned.
See method >getAddrElement_FieldJc(...), this methods accesses inside the container with a given index.
instance: MemSegmJc - the Object. It shouln't derivated from ObjectJc, it may be any struct or class, but the type should matched to the ClassJc description getted with getDeclaringClass_FieldJc(ythis).
sVaargs: char - The method can have one or more indices to index an element in the array, if ythis is an array-field. The sVaarg-string contains one or more characters "I" to designate that the following variable arguments are from type int. This concept of processing a variable argument list is established with the Java2C-translator. In Java the type of the elements of a variable argument list are well known in Runtime, other than its usual in C. This String defines the types. It the type is null or empty, no variable arguments are given.
vaargs: va_list - indices for indexing an array element.
returns: MemSegmJc - if the container is an embedded element, this method returns the same value as getMemoryAddress_FieldJc(...), but if it is referenced, the referenced address is returned. The bits mContainerReference_Modifier_reflectJc in bitModifiers are tested to get the result.
Gets the address of the element described with the field of the given object. It regards whether the field is of container type, it regards the index.
instance: MemSegmJc -
sVaargs: char - The method can have one or more indices to index an element in the array, if ythis is an array-field. The sVaarg-string contains one or more characters "I" to designate that the following variable arguments are from type int. This concept of processing a variable argument list is established with the Java2C-translator. In Java the type of the elements of a variable argument list are well known in Runtime, other than its usual in C. This String defines the types. It the type is null or empty, no variable arguments are given.
vaargs: va_list - indices for indexing an array element.
returns: MemSegmJc - s the address of the reference maybe in a container or the address of the reference immediately, if it isn't a container.
If the contained instances in the container are embedded in the container, this address is equal with the address of the instance.
If the instances in the container are references, this is the address where the reference to the instance is found. The type
of the reference should be regarded. Check (getModifiers_FieldJc(field) & mAddressing_Modifier_reflectJc)
to detect which to do whith the address.
throws - IndexOutOfBoundsException if the idx is fault.
since - 2009-11-26, it is necessary to set references with the inspector-Tool.
Gets the absolute address of the indexed element of a UML-specific container element known as UML_LinkedList. The algorithm should be specified in the users area (extra file.c) because it is UML-Framework-specific.
container: MemSegmJc -
sVaargs: char -
vaargs: va_list -
returns: MemSegmJc -
throws - IndexOutOfBoundsException if the idx is fault.
Gets the absolute address of the indexed element of a UML-specific container element known as UML_ArrayList. The algorithm should be specified in the users area (extra file.c) because it is UML-Framework-specific.
container: MemSegmJc -
sVaargs: char -
vaargs: va_list -
returns: MemSegmJc -
throws - IndexOutOfBoundsException if the idx is fault.
Gets the absolute address of the indexed element of a UML-specific container element known as UML_Map. The algorithm should be specified in the users area (extra file.c) because it is UML-Framework-specific.
container: MemSegmJc -
sVaargs: char -
vaargs: va_list -
returns: MemSegmJc -
throws - IndexOutOfBoundsException if the idx is fault.
Gets the object represented by the Field ythis from an given object. If it is not a complex datatype but an simple type (int, float and others), this method returns null. This is in opposite to Java, java wrappes the primitive type.
If the object it is a C++ class and it is derived from ObjectJc, this method returns the pointer to the baseclass ObjectJc
of the instance. If the instance itself with its really type should be gotten, a <dynamic_cast>(ptr)
is necessary, usual in C++.
If the object isn't based on ObjectJc, the address of that entry in the instance is returned, which is matching to the type of the field. It means, if multi-inheritance is used in C++, it may not be the really address of the instance. Than a dynamic_cast from the known pointer with the correct type to the type of the instance supplies the really instance-address. The type of the instance isn't able to evaluate with reflection in this case, it should be known by the programmer.
If the object is located in an external memory, the reference in that memory with the adequate segment information is returned.
instance: MemSegmJc -
sVaArgIdx: char -
returns: MemSegmJc -
obj: ObjectifcBaseJcpp -
idx: int -
returns: MemSegmJc -
Searches an object with given start object and path. This is a static method in context of ClassJc. The returned object may be based on ObjectJc or not. In C/C++ systems, especially in user oriented data structures, the inheritance of ObjectJc is not taken for granted. In this cases the describing ClassJc information will be kept as getType_FieldJc() in the Field information of this element, not in the implementing instance.
sPath: StringJc - The path to the object. At example "myObj.theElement[20].x"
.
startObj: ObjectJc - The object from which the path starts, it have to be based on ObjectJc.
field: FieldJc - Reference to a FieldJc reference, it will be set as return with the last found Field information.
idx: int - Reference to a int, it will be set as return with the last found index information in path, or set to -1 if no index is given at last position.
returns: MemSegmJc - The founded object matching to the returned field. The Object is the last but one part of the VariablePath, but the returned field is the last part of the Variable path. The returned idx is >=0 if the last part contains an index information.
Gets the Object and the describing class of the Object from given FieldJc in given object. See get_FieldJc(...) If the object is non based on ObjectJc, it hasn't own reflection infos inside it, but the reflection info to the pointer to it is known as a Class type, returned by getType_FieldJc. In this case this information is supplied. The class info always matches to the returned obj. If the field describes a primitive type, it returns null and sets obj to null.
instance: MemSegmJc -
retClazz: -
sVaargs: char -
returns: MemSegmJc -
Gets the actual length of the array if the field describes a reference of an array or collection,
instance: MemSegmJc -
returns: int - the actual length, it may be 0.
throws - NoSuchFieldException if it describes not an array or collection.
instance: MemSegmJc -
returns: int -
instance: MemSegmJc -
returns: int -
instance: MemSegmJc -
returns: int -
instance: MemSegmJc -
sVaargs: char -
returns: bool -
instance: MemSegmJc -
sVaargs: char -
returns: char -
instance: MemSegmJc -
sVaargs: char -
returns: int8 -
instance: MemSegmJc -
sVaargs: char -
returns: int16 -
instance: MemSegmJc -
sVaargs: char -
returns: int32 -
Set the bits of a bitfield descibed by the given field.
instance: MemSegmJc -
sVaargs: char -
returns: int16 - The value for the bits. The bits are adjusted rigth here, they will be shifted from the correct bit position. NOTE: It is a int-value, may be 16 bit, because the register width is proper for that.
javalike - : Because java doesn' know bitfields, it isn't java-like, but it is proper and necessary for C-programming.
instance: MemSegmJc -
sVaargs: char -
returns: float -
instance: MemSegmJc -
sVaargs: char -
returns: double -
Gets a String representation of the content of this FieldJc in the given instance. <ul> <li>If the field is a Object-compatible type (a reference) and the reference is not null, then the Object.toString()-method is invoked with this reference. <li>If the reference is null, than "null" is returned. <li>If the field is a primitive type, the String representation of its content is returned. <li>For C-usage: If the field references a non-Object-instance, "
instance: MemSegmJc - The instance where this FieldJc is member of.
sVaargs: char -
returns: StringJc - A String which represents the content of the field.
addr - " is returned, where addr is the memory address of the referenced instance (the reference value). </ul>
throws - IllegalArgumentException
throws - IllegalAccessException
Returns the reference to the field inside the given object. This method is not javalike. Because the type of the field is not known in this context, the reference is of type void*. The user should cast it outside to the type of the field. The casting is only admissible to the exactly type of the field. If it is a primitive type, the reference may be casted to the reference to the primitive type, such as (int*). If the reference is a complex type, especially a interface in C++, the cast is only admissible to the interface type, not to a supposed derivated type. The casting to a derivated type in C++ is only admissible with static_cast<type>, because the compiler should adjust the reference.
instance: MemSegmJc -
sVaargs: char -
returns: MemSegmJc -
since - 2010-07-01: Uses anyway, returns the address of the container or primitive type, if it isn't a reference, returns the reference to the instance if it is a reference.
instance: MemSegmJc -
sVaargs: char -
vaargs: va_list -
returns: MemSegmJc -
instance: MemSegmJc -
sVaargs: char -
returns: int32 -
instance: MemSegmJc -
sVaargs: char -
vaargs: va_list -
returns: int32 -
instance: MemSegmJc -
sVaargs: char -
returns: int64 -
obj: MemSegmJc -
val: bool -
sVaargs: char -
returns: bool -
obj: MemSegmJc -
val: char -
sVaargs: char -
returns: char -
obj: MemSegmJc -
val: int8 -
sVaargs: char -
returns: int8 -
obj: MemSegmJc -
val: int16 -
sVaargs: char -
returns: int16 -
instance: MemSegmJc -
val: int -
sVaargs: char -
returns: int32 -
obj: MemSegmJc -
val: int64 -
sVaargs: char -
returns: int64 -
Set the bits of a bitfield descibed by the given field.
obj: MemSegmJc - The object to set the value inside.
val: int - The value for the bits. The bits are adjusted rigth here, they will be shifted to the correct bit position. NOTE: It is a int-value, may be 16 bit, because the register width is proper for that.
sVaargs: char -
returns: int -
javalike - : Because java doesn' know bitfields, it isn't java-like, but it is proper and necessary for C-programming.
instance: MemSegmJc -
val: float -
sVaargs: char -
returns: float -
obj: MemSegmJc -
val: double -
sVaargs: char -
returns: double -
Sets a reference at the desired field in the given object obj. The field should be a reference type of a scalar or not object-based instance. In other cases (if it is a scalar direct or a object base reference), the method throws IllegalArgumentException. Use set_FieldJc to assign a reference to a object-based instance. The method don't check anything. This method isn't exist in java, because java don't know references.to not object base instances.
instance: MemSegmJc -
value: void - The reference to the destination instance to set in the object's field.
sVaargs: char -
returns: void -
exception - IllegalArgumentException if the methode doesn't match to the arguments.
size: int -
returns: -
CONST-Initializer sind Makros für C-Konstanten, sie sind in Headerfiles definiert. C-Konstante sind Konstrukte in { ... } mit ausschließlich konstanten Werten. Die Makros der CONST-Initializer übernehmen Argumente, die zur Compilezeit die Konstanten bestimmen. Die Initializer sind deshalb als Makros definiert, weil die Struktur der Konstanten exakt der struct-Definition folgen muss, die struct ist im Headerfile definiert, daher auch dazu passend diese Makros. Mit denCONST-Intializer ist es auf einfache Weise möglich, C-struct-Daten (Plain Old Data) zu initialisieren. Für Klassen (C++) ist dieses Konzept nicht geeignet.
Defines the constant value of a field instance. The followed defines have to be defined before:
REFLECTION_CURRENTJc
SNAME -
NAME -
TYPE -
MODI -
Macro for a constant head of FieldJc array useable to define the constants for reflection. New since 2007.09
NAME -
Macro for a constant head of FieldJc array useable to define the constants for reflection. New since 2007.09
SIZE -
OWNADDRESS -
Defines a field as constant structure.
SNAME - name of field element as string literal.
OFFSET -
TYPE - type of the name, with Reflection_NAME the associated classJc is designated.
MODI - Mofifier, using values of enum type Modifier_reflectJc_t.
Constant Definition of a FieldJc-instance inside a whole reflection definition.
CLASS - Name of the Type wherein this field is defined. The Value is used to calculate the offset of the element and to build the pointer to the declaring class in Form reflection##CLASS.clazz.
SNAME - String given name of the field. It should be identical with NAME, but with quotion marks.
NAME - identifier of the element inside the Type CLASS.
TYPE - The type of the the element, the reflection class is build with reflection##TYPE
MODI - Modifier, see CLASS_C ModifierJc.
UML=/Package[ReflectionJc_h]/Namespace.ownedElement[]/Class[MethodJc]
Class MethodJc im Package ReflectionJc_h
UML=/Package[ReflectionJc_h]/Namespace.ownedElement[]/Class[MethodJc]
+-------'-------'-------'-------'-------'-------'-------'--...32+
| name |
+-------'-------'-------'-------+-------'-------'-------'--...8+
| bModifiers | adress |
+-------'-------'-------'-------'-------'-------'-------'-------+
| eType |
+-------'-------'-------'-------'-------'-------'-------'-------
Modifier see java class Modifier
adress of the method
Type of the method
returns: StringJc -
Invokes the underlying method represented by this Method object, on the specified object with the specified parameters. Individual parameters are automatically unwrapped to match primitive formal parameters, and both primitive and reference parameters are subject to method invocation conversions as necessary. <br/>
If the underlying method is static, then the specified obj argument is ignored. It may be null. <br/>
If the number of formal parameters required by the underlying method is 0, the supplied args array may be of length 0 or null. <br/>
If the underlying method is an instance method, it is invoked using dynamic method lookup.<br/>
instance: MemSegmJc -
params: -
returns: int32 -
obj: ObjectJc -
params: -
returns: int32 -
idx: int -
returns: MethodJc -
Converts a Array of type MethodJcARRAY with any desired size to the given MethodJcARRAY-Type. The conversion may test the content or not.
ptr: ObjectArrayJc -
returns: -
CONST-Initializer sind Makros für C-Konstanten, sie sind in Headerfiles definiert. C-Konstante sind Konstrukte in { ... } mit ausschließlich konstanten Werten. Die Makros der CONST-Initializer übernehmen Argumente, die zur Compilezeit die Konstanten bestimmen. Die Initializer sind deshalb als Makros definiert, weil die Struktur der Konstanten exakt der struct-Definition folgen muss, die struct ist im Headerfile definiert, daher auch dazu passend diese Makros. Mit denCONST-Intializer ist es auf einfache Weise möglich, C-struct-Daten (Plain Old Data) zu initialisieren. Für Klassen (C++) ist dieses Konzept nicht geeignet.
NAME -
CLASS -
SNAME -
NAME -
TYPE -
MODI -