(27.08.2014 07:12 )galilio schrieb: @rolfk
danke für deine Antwort.
-->rolfk schrieb:
CEFI_Out_Wrapper scheint nicht verwendet aber den solltest Du auch nicht als Funktionsparameter/Rückgabewert irgendwo verwenden.
sondern wie mache ich das denn ?
LabVIEW Strings sind KEINE C Strings. Du kannst also nicht LabVIEW Strings in einen Cluster stopfen und hoffen dass die C String Pointer automagisch in LabVIEW Strings umgewandelt werden. Du musst also einen Cluster machen wo anstelle des C String Pointers ein Integer ist. Dieser muss 32 bit sein wenn Du in LabVIEW 32 Bit bist und 64 Bit wenn Du in LabVIEW 64 Bit bist. Danach musst Du nachdem die Funktion den Cluster zurückgegeben hat jeden Pointer einzeln in einen LabVIEW String kopieren. Dies geschieht durch Aufruf von LabVIEW Manager Funktionen wie in
diesem Thread erklärt (in Englisch).
Und wenn die Strings nicht irgendwie statisch in der DLL liegen sondern mit malloc oder ähnlichem angelegt werden musst Du danach diese auch wieder deallozieren. Das darfst Du nicht mit LabVIEW Funktionen machen sondern dafür musst Du eine weitere Funktion exportieren die mit alle Pointer mit den entsprechenden Funktionen in Deiner Library dealloziert.
Wenn Du diese Struktur über den Funktionsrückgabewert übergibst musst Du ausserdem auch noch den Cluster vom Rückgabepointer in eine LabVIEW Cluster kopieren. Wenn Du das hingegen über einen Funktionsparameter machst kannst Du diesen in der Call Library Node als Adapt to Type konfigurieren und dann eine LabVIEW Cluster mit der richtigen Datenstruktur daran verbinden. Dann füllt die Funktion diese ein.
Ausserdem hast Du dann noch das Problem von Alignment. Das heisst dass der C Compiler normalerweise (default Einstellungen) alle Elemente in einer struct auf eine Adresse legt die ein Vielfaches des kleineren Wertes der beiden Grössen Elementgrösse und Defaultalignment (Visual C benützt hier default 8) ist.
Hier ein Beispiel:
Code:
struct
{
char val;
char *string;
}
wird in 32 Bit im Speicher durch den C Compiler so angelegt, bei default Einstellungen:
Code:
struct
{
char val;
char filler[3]; // The following pointer uses 4 Bytes so it must start on a multiple of 4 bytes from the start of the structure.
char *string;
}
und in 64 Bit:
Code:
struct
{
char val;
char filler[7]; // The following pointer uses 8 Bytes so it must start on a multiple of 8 bytes from the start of the structure.
char *string;
}
LabVIEW verwendet aber unter Windows für die eigenen Datenstrukturen das sogenannte Packed Format. D.h. es fügt keine Filler in die Cluster ein. Das ist kein Fehler, denn das Alignment bei C Compilern ist mittels Compiler Optionen einstellbar. D.h. wenn LabVIEW das Visual C Default Alignment verwenden würde wäre das Interfacing zu externen Libraries die mit einem anderen Alignment kompiliert wurden fast unmöglich. So muss man nur selber daran denken dass man bei den Clustern die man an externe Funktionen übergibt das entsprechende Alignment durch extra Dummyelemente garantiert.
BOOL ist nicht gleich bool. Das erste ist ein Windows API Datentyp der tatasächlich ein 32 Bit Integer ist. Das zweite ist ein C11 Datentyp (nur in C++ und allerneusten C Compilern unterstützt). C11 spezifiziert keinen bestimmte Datengrösse sondern überlässt dies den Compilerbauern. Praktischerweise verwendet zumindest Visual C hier ein Byte, aber anderen Compilern ist es freigestellt etwas anderes zu verwenden.
EFILib ist eigentlich ein Object-Pointer. Die Grösse von einem Pointer ist abhängig vom Memorymodell. Konfiguriere diese Parameter deshalb als Pointer sized Integer und verwende im LabVIEW Diagramm einen U64.