Problem beim Verwenden von 2D Arrays - Druckversion +- LabVIEWForum.de (https://www.labviewforum.de) +-- Forum: LabVIEW (/Forum-LabVIEW) +--- Forum: LabVIEW Allgemein (/Forum-LabVIEW-Allgemein) +---- Forum: DLL & externer Code (/Forum-DLL-externer-Code) +---- Thema: Problem beim Verwenden von 2D Arrays (/Thread-Problem-beim-Verwenden-von-2D-Arrays) |
Problem beim Verwenden von 2D Arrays - grey - 29.02.2008 11:18 Hallo, ich möchte aus LV in ein C Programm ein 2D Array einlesen, daraus Berechnungen anstellen und die Ergebnisse anschließend in ein neues 2D Array schreiben, das dann wieder an LV übergeben werden soll. Leider scheint es jedoch mit diesen 2D Arrays Probleme zu geben, denn immer wenn ich sie im C Programm anspreche gibt LV einen fehler heraus, mache ich testweise nur eine Berechnung mit den anderen übergebenen Werten funktioniert dies und ich erhalte keinen Fehler. Meine Funktion lautet folgendermaßen: long KontrastC(long *Brows, long *Bcols, long *Lcols, long *Lrows, unsigned char **Bild, double **Kontrast,long *test) Brows,Bcols geben die Größe des neuen 2D Arrays "Kontrast" an. Lcols und Lrows geben an in wie große, ich nenne es mal, Teilarrays das ursprüngliche 2D Array "Bild" zerlegt werden soll, was für die Berechnung wichtig ist aber auch für die Größe des neuen Ausgangsarrays. test ist einfach nur eine Variable die ich zum testen einfacher berechnung ohne Arrays verwendete. LabVIEW schlägt als Funktionsprototyp übrigens folgendes vor: long KontrastC(long *Brows, long *Bcols, long *Lcols, long *Lrows, unsigned char *Bild, double *Kontrast,long *test) Das erscheint mir und dem Kompiler jedoch als sehr unsinnig da definitiv ein 2D Array eingestellt wurde. Als Array Datentyp wurde übrigens "Array Datenzeiger" bei den beiden 2D Arrays Kontrast und Bild eingesetzt. Der C-Code lautet: /*Programm zur Kontrastberechnung und Bildarrayzerlegung Brows=Reihenanzahl des neuen Bildarrays (Kontrastbild) von LabVIEW errechnet und übergeben Bcols=Kolumnenanzahl des neuen Bildarrays (Kontrastbild) von LabVIEW errechnet und übergeben Lrows=Reihenanzahl eines Teilarrays von LabVIEW übergeben Lcols=Kolumnenanzahl eines Teilarrays von LabVIEW übergeben Bild=Das Bildarray des ursprünglichen Bildes welches von LabVIEW übergeben wurde Kontrast=Errechnetes Kontrastbild welches an LabVIEW übergeben werden soll */ /* Call Library source file */ #include "extcode.h" #include <stdio.h> #include <stdlib.h> __declspec(dllexport) long KontrastC(long *Brows, long *Bcols, long *Lcols, long *Lrows, unsigned char **Bild, double **Kontrast,long *test); //Hauptprogramm Kontrastberechnung double* callocvector(int); double* freevector(double*); double** callocmatrix(int, int); double** freematrix(double**,int); long KontrastC(long *Brows, long *Bcols, long *Lcols, long *Lrows, unsigned char **Bild, double **Kontrast,long *test) { /* *test=*Lrows * *Lcols; Kontrast[1][1]=777; return 0; } */ int i=0,j=0,m=0,n=0; double** Mittelwert = callocmatrix(*Brows,*Bcols); //double** Kontrast = callocmatrix(*Brows,*Bcols); // Mittelwertsberechnung for (m=0;m<=*Brows;i++) { for(n=0;n<=*Bcols;n++) { for (i=0;i<=*Lrows;i++) { for(j=0;j<=*Lcols;j++) { Mittelwert[m][n]=Mittelwert[m][n]+Bild[i+(m * *Lrows)][j+(n * *Lcols)]; } } Mittelwert[m][n]=( 1.0/(*Lrows * *Lcols) )* Mittelwert[m][n]; } } //Kontrastberechnung for (m=0;m<=*Brows;i++) { for(n=0;n<=*Bcols;n++) { for (i=0;i<=*Lrows;i++) { for(j=0;j<=*Lcols;j++) { Mittelwert[m][n]=Mittelwert[m][n]+Bild[i+(m * *Lrows)][j+(n * *Lcols)]; Kontrast[m][n]=Kontrast[m][n]+( (Bild[i+(m * *Lrows)][j+(n * *Lcols)]-Mittelwert[m][n]) *(Bild[i+(m * *Lrows)][j+(n * *Lcols)]-Mittelwert[m][n]) ); } } Kontrast[m][n]=( 1.0/(*Lrows * *Lcols) )* Kontrast[m][n]; } } //Freigeben des reservierten Speichers //Kontrast = freematrix(Kontrast,Lrows); Mittelwert = freematrix(Mittelwert,*Lrows); return 0; } //Unterprogramme zur dynamischen Speicherallokation /*-------------------------------------------- "callocvector" allocates the memory for a dynamic vector of length n and initializes it --------------------------------------------*/ double* callocvector(int n) { int j; double* vector = calloc(n,sizeof(double)); for (j=0; j<n; j++) { vector[j] = 0; } return(vector); } /*-------------------------------------------- "freevector" dis-allocates the memory of a dynamic vector of arbitrary length and sets the pointer to NULL --------------------------------------------*/ double* freevector(double* vector) { free(vector); return(NULL); } /*-------------------------------------------- "callocmatrix" allocates the memory for a dynamic matrix of size (m times n) and initializes it --------------------------------------------*/ double** callocmatrix(int m, int n) { int i; double** matrix = calloc(m,sizeof(double)); for (i=0; i<m; i++) { matrix[i] = callocvector(n); } return(matrix); } /*-------------------------------------------- "freematrix" dis-allocates the memory of a dynamic matrix of size (m times n) and sets the pointer to NULL --------------------------------------------*/ double** freematrix(double** matrix,int m) { int i; for (i=0; i<m; i++) { free(matrix[i]); free(matrix); } return(NULL); } Problem beim Verwenden von 2D Arrays - IchSelbst - 29.02.2008 13:14 ' schrieb:long KontrastC(long *Brows, long *Bcols, long *Lcols, long *Lrows, unsigned char **Bild, double **Kontrast,long *test) Zitat:LabVIEW schlägt als Funktionsprototyp übrigens folgendes vor:Der Unterschied ist offensichtlich: "unsigned char *" ist was ganz was anderes als "unsigned char **". Zitat:Das erscheint mir und dem Kompiler jedoch als sehr unsinnig da definitiv ein 2D Array eingestellt wurde.** heißt nicht, dass es sich um eine 2D-Array handelt. ** ist ein Zeiger auf den Instanzzeiger des Arrays. Zitat:Als Array Datentyp wurde übrigens "Array Datenzeiger" bei den beiden 2D Arrays Kontrast und Bild eingesetzt.Bei "Array Datenzeiger" nur ein Stern. Bei zwei Sternen könntest du "Zeiger auf Array-Handle" probieren (da bin ich aber unsicher). Zitat:Der C-Code lautet:Kannst du den C-Code ändern? Mach aus ** * und pass den Code entsprechend an (z.B. (Selbst-Inkrementierende-) Pointern anstelle explizitem Array-Zugriff). Die Übergabe ist dann "Array Datenzeiger". Problem beim Verwenden von 2D Arrays - grey - 29.02.2008 16:22 Vielen Dank für die rasche Antwort. Ich habe zwar noch nie wirklich etwas mit Selbst Inkrementierenden Zeigern gemacht, denke aber, dass so wie ich das nun eingebaut habe in die richtige richtung gehen müßte. Leider gibt mir der Compiler nun die Fehlermeldung "Ungültige Dereferenzierung" heraus, was mir sagt, dass ich da doch noch etwas recht wichtiges übersehen haben müßte. Das wundert mich insofern, da ein kleines Testprogramm mit dem ich mal diese Selbst Inkrementierenden Zeiger, an einer selbst gebastelten Matrix, ausprobierte recht gut lief. Des weiteren erhalte ich noch eine Fehlermeldung " error C2106: '=': Linker Operand muss ein L-Wert sein" an den Stellen an denen ich die Dinge letztlich in das Kontrastarray schreiben möchte, dieser erscheint nicht wenn man es über Kontrast[m][n] anspricht, obwohl es ja, so wie ich das verstand, genau das Gleiche sein müßte wie *(*(Kontrast+m)+n) . Ich poste hier mal den neuen Code und hoffe, auf weitere Hinweise auf das was ich noch übersehen habe/ bzw. falsch mache. /*Programm zur Kontrastberechnung und Bildarrayzerlegung Brows=Reihenanzahl des neuen Bildarrays (Kontrastbild) von LabVIEW errechnet und übergeben Bcols=Kolumnenanzahl des neuen Bildarrays (Kontrastbild) von LabVIEW errechnet und übergeben Lrows=Reihenanzahl eines Teilarrays von LabVIEW übergeben Lcols=Kolumnenanzahl eines Teilarrays von LabVIEW übergeben Bild=Das Bildarray des ursprünglichen Bildes welches von LabVIEW übergeben wurde Kontrast=Errechnetes Kontrastbild welches an LabVIEW übergeben werden soll */ /* Call Library source file */ #include "extcode.h" #include <stdio.h> #include <stdlib.h> __declspec(dllexport) long KontrastC(long *Brows, long *Bcols, long *Lcols, long *Lrows, unsigned char *Bild, double *Kontrast,long *test); //Hauptprogramm Kontrastberechnung double* callocvector(int); double* freevector(double*); double** callocmatrix(int, int); double** freematrix(double**,int); long KontrastC(long *Brows, long *Bcols, long *Lcols, long *Lrows, unsigned char *Bild, double *Kontrast,long *test) { /* *test=*Lrows * *Lcols; Kontrast[1][1]=777; return 0; } */ int i=0,j=0,m=0,n=0; double** Mittelwert = callocmatrix(*Brows,*Bcols); //double** Kontrast = callocmatrix(*Brows,*Bcols); // Mittelwertsberechnung for (m=0;m<=*Brows;i++) { for(n=0;n<=*Bcols;n++) { for (i=0;i<=*Lrows;i++) { for(j=0;j<=*Lcols;j++) { //Mittelwert[m][n]=Mittelwert[m][n]+Bild[i+(m * *Lrows)][j+(n * *Lcols)]; Mittelwert[m][n]=Mittelwert[m][n]+ *( *(Bild+i+(m * *Lrows))+j+(n * *Lcols) ); } } Mittelwert[m][n]=( 1.0/(*Lrows * *Lcols) )* Mittelwert[m][n]; } } //Kontrastberechnung for (m=0;m<=*Brows;i++) { for(n=0;n<=*Bcols;n++) { for (i=0;i<=*Lrows;i++) { for(j=0;j<=*Lcols;j++) { //Kontrast[m][n]=Kontrast[m][n]+( (Bild[i+(m * *Lrows)][j+(n * *Lcols)]-Mittelwert[m][n]) // *(Bild[i+(m * *Lrows)][j+(n * *Lcols)]-Mittelwert[m][n]) ); *(*(Kontrast+m)+n)=*(*(Kontrast+m)+n) + ( *( *(Bild+i+(m * *Lrows))+j+(n * *Lcols) )-Mittelwert[m][n]) *( *(*(Bild+i+(m * *Lrows))+j+(n * *Lcols) )-Mittelwert[m][n] ); } } //Kontrast[m][n]=( 1.0/(*Lrows * *Lcols) )* Kontrast[m][n]; *(*(Kontrast+m)+n)=( 1.0/(*Lrows * *Lcols) )* *(*(Kontrast+m)+n); } } //Freigeben des reservierten Speichers //Kontrast = freematrix(Kontrast,Lrows); Mittelwert = freematrix(Mittelwert,*Lrows); return 0; } //Unterprogramme zur dynamischen Speicherallokation /*-------------------------------------------- "callocvector" allocates the memory for a dynamic vector of length n and initializes it --------------------------------------------*/ double* callocvector(int n) { int j; double* vector = calloc(n,sizeof(double)); for (j=0; j<n; j++) { vector[j] = 0; } return(vector); } /*-------------------------------------------- "freevector" dis-allocates the memory of a dynamic vector of arbitrary length and sets the pointer to NULL --------------------------------------------*/ double* freevector(double* vector) { free(vector); return(NULL); } /*-------------------------------------------- "callocmatrix" allocates the memory for a dynamic matrix of size (m times n) and initializes it --------------------------------------------*/ double** callocmatrix(int m, int n) { int i; double** matrix = calloc(m,sizeof(double)); for (i=0; i<m; i++) { matrix[i] = callocvector(n); } return(matrix); } /*-------------------------------------------- "freematrix" dis-allocates the memory of a dynamic matrix of size (m times n) and sets the pointer to NULL --------------------------------------------*/ double** freematrix(double** matrix,int m) { int i; for (i=0; i<m; i++) { free(matrix[i]); free(matrix); } return(NULL); } Problem beim Verwenden von 2D Arrays - IchSelbst - 29.02.2008 19:09 ' schrieb:Selbst Inkrementierenden ZeigernDamit meinte ich eigentlich sowas wie "Value = (*(Bild++));" Dieses Verfahren, das etwas komplizierter ist in der Programmierung, geht schneller als der Array-Zugriff (der dafür einfacher zu programmieren ist). [code]for (m=0;m<=*Brows;i++) { Problem beim Verwenden von 2D Arrays - grey - 03.03.2008 11:05 Hm bevor ich das anständig implementieren kann wäre es wohl gut, wenn ich das nun auch nachvollziehen könnte. Leider habe ich gerade etwas Probleme damit, zu verstehen, wie auf diese Weise der explizite Zugriff auf das gewünsvhte Arrayelement geschieht. Dieser wird wohl durch die Zeilen " MyBild2 = Bild + m * ????; " irgednwie initialisiert aber wie da eine 2D Steuerung zusammenkommt ist mir doch ein Rätsel. Ich habe aber mal etwas herumgeschaut und gesehen, dass nicht nur BeispielZeiger++ möglich ist, sondern auch so etwas wie BeispielZeiger+=4 wenn man eben vier stellen weiter springen möchte. Könnte man es dadurch vielleicht vereinfachen? Nur ist hierbei dann die Frage wie ich ihm eben die getrennten Koordinaten eines 2D Arrays mitteile, beispielsweise wenn er in xRichtung vier Stellen weiterspringen soll, in Y aber nur beispielsweise zwei. Allgemein finde ich leider keine Beispiele oder die Syntax zu diese selbstinkrementierenden Zeigern. Ich hoffe das fängt nun nicht an zu sehr zu langweilen aber man will ja auch verstehen was man macht und ich fürchte das wird noch ein nicht allzu kurzer Lernprozeß werden. Problem beim Verwenden von 2D Arrays - IchSelbst - 03.03.2008 11:18 Hast du denn zuerst mal so probiert, wie du es von Anfang an hattest, also mit dem Array-Zugriff - aber eben nur mit einem * anstelle von ** in der Headerzeile? Problem beim Verwenden von 2D Arrays - IchSelbst - 03.03.2008 12:02 Ich hab noch mal was verfasst. [code]for (m=0;m<*Brows;i++) Problem beim Verwenden von 2D Arrays - grey - 03.03.2008 13:52 Also die Änderung von ** auf * bringt nur folgenden Fehler hervor: "error C2109: Index erfordert ein Array oder einen Zeigertyp" Mit dem < statt <= hast du übrigens recht, da war ich wohl wieder gedanklich in irgendeiner anderen Programmiersprache gefangen, wie es aussieht. Inzwischen habe ich aber auch mal Beispiele zur Übergabe an eine DLL von NI selbst gefunden [code]#include "extcode.h" _declspec(dllexport) void ARRAY2D(double *array, Problem beim Verwenden von 2D Arrays - IchSelbst - 03.03.2008 14:47 ' schrieb:Also die Änderung von ** auf * bringt nur folgenden Fehler hervor:Du hast das aber mit dem Source, wie er in deinem ersten Posting hier steht, probiert? Und das geht nicht? Zitat:Inzwischen habe ich aber auch mal Beispiele zur Übergabe an eine DLL von NI selbst gefundenJa, guck beim ersten Code. Da geht es auch mit nur einem Stern. Und beim zweiten scheint es ein Handle zu sein. Zitat:Außerdem wäre es sicherlich auch gut zu wissen wo der Unterschied zwischen dem Array2D und Array2DHandle genau liegt.Bei ersterem wird ein Pointer auf Daten übergeben, beim zweitem ein Pointer eben auf einen Handle. In dem Handle steht dann der Pointer auf die Daten. Willst du damit auf die Daten zugreifen, musst du zuerst auf den Handle zugreifen und dort dann den Pointer für die Daten holen. Handle ist aber so eine Sache. Ein LV-ArrayHandle sieht eben so aus, wie im zweiten Code. Im Handle würde dann auch noch drinnstehen, wie viele Dimensionen es gibt und wie groß die sind. Sogesehen enthält der Handle die Steuerinfomationen zum Feld - der Datenzeiger zeigt eben nur auf die Daten. Ob es in C++ einen ähnlichen Handle gibt oder ob der da ganz anders aussieht weiß ich nicht. Probier halt einfach mal ganz gemein aus und übergib einfach einen ArrayHandle - auf das Teil mit den zwei Sternen. Mehr als abstürzen kann er ja nicht. Ich selbst nehme immer einen Zeiger auf Daten und zähle den (in der DLL) dann "manuell" hoch. Dazu muss ich dann zwar den tatsächlichen Arrayindex selbst berechnen, aber dafür entfallen halt die Probleme mit den unterschiedlichen Datentypen in LV und C++. Problem beim Verwenden von 2D Arrays - grey - 03.03.2008 15:54 Ja, also mit der etwas verbesserten Source aus dem ersten Posting und das ergibt dann diesen genannten error C209. Ich habe das Beispiel mit dem Handle nun einmal versucht auf mein Programm anzuwenden, mir erschien das ganz nett zu sein, dass ich dadurch auch die Größe des Arrays heraus bekommen könnte, dadurch bräuchte ich dann am ende nicht mehr diese kleine Berechnung in LV zu machen und hätte mir die Brows und Bcols Übergabe gespart. Dieses Programm produziert dann aber wiederum folgende Fehlermneldungen beim kompilieren: error C2223: Der linke Teil von '->dimSizes' muss auf eine Struktur/Union zeigen bzw. error C2223: Der linke Teil von '->elt' muss auf eine Struktur/Union zeigen Das wird wohl an den Funktionszeilen liegen schätze ich. In meinem Programm habe ich es folgenermaßen versucht: _declspec(dllexport) long KontrastC(long *Brows, long *Bcols, long *Lcols, long *Lrows, TD1Hd1 *Bild, TD1Hd1 *Kontrast,long *test); Probeweise auch einmal so: _declspec(dllexport) long KontrastC(long *Brows, long *Bcols, long *Lcols, long *Lrows, TD1Hd1 **Bild, TD1Hd1 **Kontrast,long *test); Wenn ich in LV die Konfiguration auf Array Handle stelle nennt er mir aber folgenden Funktionsprototyp: _declspec(dllexport) long KontrastC(long *Brows, long *Bcols, long *Lcols, long *Lrows, Array2DUnsigned char **Bild, Array2DDouble *Kontrast,long *test); Aber ich kann meine Struktur ja schlecht Array2DUnsigned char nennen und schon gar nicht gleichzeitig noch Array2DDouble Im Beispiel war es ja auch nun einmal TD1Hd1 allerdings mit dem Namen "array" hinter -wobei ich da davon ausging, dass der durch Bild und Kontrast zu ersetzen sein. Davon gehe ich eigentlich immernoch aus, wundere mich jedoch darüber, dass "array" blau wurde, das aber nicht mit Bild und Kontrast geschieht. Deine Lösung ist sicherlich nicht zu verachten allerdings muß ich gestehen da noch erhebliche Probleme beim Ausrechnen der richtigen Werte zu haben, da habe ich bisher noch keinen wirklichen Zugang zu gefunden. [code]/*Programm zur Kontrastberechnung und Bildarrayzerlegung |