Forum: PC-Programmierung wrapper in c (quellcode ist C++ und QT)


von Daniel (Gast)


Lesenswert?

Hallo alle zusammen,

folgende Problematik ist:

Einen bestehenden Code (C++ und QT "4.8").
Aus dieses Code kann man einen DLL File erstellen. Was auch machbar ist.

Nun wollte ich dieses DLL in Labview (als Library importieren) 
integrieren.
Das kann ich auch teilweise lösen in dem ich einen C_Wrapper schreiben 
und in Labview importieren (so viel zu Theorie).

Meine Frage an euch ist:

Wie machbar ist meinen Vorhaben?
Da QT teilweise Complexe Datentyp beinhaltet wie QString, QList und 
.....,
kann ich nicht schätzen wie umständlich ist meine Vorhaben?

: Verschoben durch User
von Klaus W. (mfgkw)


Lesenswert?

Daniel schrieb:
> kann ich nicht schätzen wie umständlich ist meine Vorhaben?

kann ich auch nicht.

Kommt drauf an, wie viele Funktionsaufrufe du umsetzen musst und wie fit 
du bist.

von Nase (Gast)


Lesenswert?

Bau eine C-taugliche Schnittstelle und exportier die:
1
extern "C" {
2
...
3
}

Alles andere wird mutig, spätestens wenns mit dem name mangling losgeht.

von Daniel (Gast)


Lesenswert?

Klaus W. schrieb:
> Kommt drauf an, wie viele Funktionsaufrufe du umsetzen musst und wie fit
> du bist.

ja das stimmt.
In Labview habe ich nur Grundwissen und meinen Arbeitsgeber ist auch 
bereit eine Weiterbildung zu bezahlen falls nötig aber meine Frage ist:
Ist das überhaupt machbar trotz der komplexen QT Datentypen.

von db8fs (Gast)


Lesenswert?


von Klaus W. (mfgkw)


Lesenswert?

Daniel schrieb:
> Ist das überhaupt machbar trotz der komplexen QT Datentypen.

Dein Labview wird damit nichts anfangen können, deshalb musst du doch 
eine Zwischenschicht bauen. Aber nur du kannst wissen, was alles darüber 
gehen soll.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Daniel schrieb:
> Ist das überhaupt machbar trotz der komplexen QT Datentypen.

Die darfst Du in Deinem C-Interface nicht exportieren, sondern musst in 
C verwendbare Datentypen nutzen und entsprechend hin- und 
herkonvertieren.

Darum muss sich Dein Wrapper kümmern; da Du ja nicht die Funktionalität 
von QT selbst anbieten willst, sondern nur die eines mit QT 
geschriebenen Programmes, sollte das realisierbar sein.

Mach Dir also zuerst mal Gedanken darüber, welche Funktionen denn Deine 
DLL zur Verfügung stellen muss, und dann, falls dabei Funktionen sind, 
die QT-spezifische Datentypen nutzen, wie diese sich auf C 
transformieren lassen.

von Daniel (Gast)


Lesenswert?

Folgende vorhaben

IstStand:
Board (Pic 8 Bit)
Application (GUI), die in (C++, QT) geschrieben ist.

Board wird mit dieses Application gesteuert.
Um das Board bzw. die Kommunikation mit dem PIC zu gewährleisten ist 
einen HID.dll nötig.
Unterschiedliche Messungen werden durchgeführt und deren Ergebnis in GUI 
dargestellt, was einwandfrei lauft.

Ziel:
Einen schnittstelle für Labview zu bauen.

Wie ich vorgegangen bin:
C_Wrapper geschrieben, der die wichtigste Funktionen beinhaltet.
Dieses C_Wrapper in Labview importiert (alle Funktionen der C_Wrapper 
könnten ohne Problem importiert werden).
Labview gestartet um zu testen.(Es funktioniert leider nichts. Ich 
bekomme sogar keine Fehlermeldung).

 Meine Idee:
 Vielleicht ist die Kommunikation mit dem Board gar nicht da.
 Es muss vielleicht für die "HID.dll" auf Labview Seite was angepasst 
werden?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Schreib ein Testprogramm, das anstelle von LabView mit Deiner DLL 
kommuniziert. Dann kannst Du genauer untersuchen, was geschieht.

von physiker (Gast)


Lesenswert?

Rufus Τ. F. schrieb:
> Schreib ein Testprogramm, das anstelle von LabView mit Deiner DLL
> kommuniziert. Dann kannst Du genauer untersuchen, was geschieht.

Und natürlich unter Benutzung des Wrappers und in reinem C, um dessen 
Funktion zu testen.

von Daniel (Gast)


Lesenswert?

Hallo Zusammen,

ich habe einen Dummy Projekt (C++) "um DLL zu erstellen" erstellt und 
dafür einen C_Wrapper geschrieben:

Myclass.h
1
#pragma once
2
//#include <QString>
3
class MyClass
4
{
5
public:
6
  MyClass(double, double);
7
  ~MyClass();
8
  double Add(double,double );
9
  double Subst(double, double);
10
  double Mult(double, double);
11
  double Divid(double, double);
12
  bool Vergleich(double,double);
13
  long Avg_num(float *, long, float *);
14
  unsigned int NumInteger(char * inputString);
15
  //QString GibEinString(double, double);
16
private:
17
  double m_a, m_b;
18
};
MyClass.cpp
1
#include "stdafx.h"
2
#include "MyClass.h"
3
4
5
MyClass::MyClass(double a,double b)
6
{
7
  this->m_a = a;
8
  this->m_b = b;
9
}
10
11
MyClass::~MyClass(){ }
12
13
double MyClass::Add(double a, double b)
14
{
15
  return a+=b;
16
}
17
double MyClass::Mult(double a, double b)
18
{
19
  return a*=b;
20
}
21
double MyClass::Subst(double a, double b)
22
{
23
  return b-=a;
24
}
25
double MyClass::Divid(double a, double b)
26
{
27
  return (b / a);
28
}
29
bool MyClass::Vergleich(double a,double b)
30
{
31
  if(a>=b) return true;
32
  else return false;
33
}
34
35
long MyClass::Avg_num(float *a, long size, float *avg)
36
{
37
  //avg_num ermittelt den einfachen Durchschnitt eines Arrays numerischer Werte
38
  float sum = 0;
39
  if(a != NULL)
40
    {
41
        for(int i=0;i < size; i++)
42
        sum = sum + a[i];
43
    }
44
    else
45
        return (1);
46
    *avg = sum / size;
47
    return (0);
48
}
49
unsigned int MyClass::NumInteger(char * inputString)
50
{
51
  int lastDigit = 0;
52
    int numberOfNumbers = 0;
53
    int stringSize;
54
55
    stringSize = strlen(inputString);
56
    for(int i = 0; i < stringSize; i++)
57
    {
58
        if (!lastDigit && isdigit(inputString[i]))
59
            numberOfNumbers++;
60
        lastDigit = isdigit(inputString[i]);
61
    }
62
  //numIntegers bestimmt die Anzahl der Integer-Werte in einem String
63
    return numberOfNumbers;
64
65
}

C_Wrapper.h
1
#pragma once
2
#define DLLIMPORT __declspec (dllexport)
3
#ifdef __cplusplus
4
extern "C" { 
5
#endif
6
7
typedef struct Wrapper
8
  {
9
    void *MYClass;
10
  }Wrapper;
11
12
  DLLIMPORT Wrapper createWrapper(double a, double b);
13
  DLLIMPORT void destoryWrapper(Wrapper LV_ref);
14
15
  DLLIMPORT double Add(Wrapper LV_ref, double a, double b);
16
  DLLIMPORT double Subst(Wrapper LV_ref ,double a, double b);
17
  DLLIMPORT double Mult(Wrapper LV_ref, double a, double b);
18
  DLLIMPORT double Divid(Wrapper LV_ref, double a, double b);
19
  DLLIMPORT bool Vergleich(Wrapper LV_ref, double a, double b);
20
  DLLIMPORT long Avg_num(Wrapper LV_ref,float *a, long size, float * avg);
21
  DLLIMPORT unsigned int NumInteger(Wrapper LV_ref, char * inputString);
22
23
24
#ifdef __cplusplus
25
}
26
#endif

C_Wrapper.cpp
1
// DLL_Test_Labview.cpp : Defines the exported functions for the DLL application.
2
//
3
4
#include "stdafx.h"
5
#include "MyClass.h"
6
#include "C_DllWrapper.h"
7
8
9
DLLIMPORT Wrapper createWrapper(double a, double b)
10
{
11
  Wrapper wrapper = {static_cast<void*>(new MyClass(a,b))};
12
  return wrapper;
13
}
14
15
DLLIMPORT void destoryWrapper(Wrapper LV_ref)
16
{
17
  MyClass *myClass = static_cast<MyClass*>(LV_ref.MYClass);
18
  delete myClass;
19
}
20
DLLIMPORT double Add(Wrapper LV_ref, double a, double b)
21
{
22
  MyClass *myClass = static_cast<MyClass*>(LV_ref.MYClass);
23
  return myClass->Add(a, b);
24
}
25
26
DLLIMPORT double Mult(Wrapper LV_ref, double a, double b)
27
{
28
  MyClass *myClass = static_cast<MyClass*>(LV_ref.MYClass);
29
  return myClass->Mult(a, b);
30
}
31
32
DLLIMPORT double Subst(Wrapper LV_ref, double a, double b)
33
{
34
  MyClass *myClass = static_cast<MyClass*>(LV_ref.MYClass);
35
  return myClass->Subst(a, b);
36
}
37
38
DLLIMPORT double Divid(Wrapper LV_ref, double a, double b)
39
{
40
  MyClass *myClass = static_cast<MyClass*>(LV_ref.MYClass);
41
  return myClass->Divid(a, b);
42
}
43
DLLIMPORT bool Vergleich(Wrapper LV_ref, double a, double b)
44
{
45
  MyClass *myClass = static_cast<MyClass*>(LV_ref.MYClass);
46
  return myClass->Vergleich(a,b);
47
}
48
DLLIMPORT long Avg_num(Wrapper LV_ref,float *a, long size, float * avg)
49
{
50
  MyClass *myClass = static_cast<MyClass*>(LV_ref.MYClass);
51
  return myClass->Avg_num(a,size,avg);
52
53
}
54
DLLIMPORT unsigned int NumInteger(Wrapper LV_ref, char * inputString)
55
{
56
  MyClass *myClass = static_cast<MyClass*>(LV_ref.MYClass);
57
  return myClass->NumInteger(inputString);
58
}

--> Um dieses DLL zu testen habe ich TestProgramm geschrieben und es 
funktinoiert einwandfrei.
Ich habe auch das DLL in Labview importiert und es funktioniert.

Nun habe ich eine Frage m bezug auf meinem TestProgramm, der so 
aussieht:
1
#include "stdafx.h"
2
//#include <tchar.h>
3
#include "C_DllWrapper.h"
4
#include <iostream>
5
using namespace std;
6
7
int _tmain(int argc, _TCHAR* argv[])
8
{
9
  Wrapper wrapper = {}; // Wie soll ich meinen struct initialisieren ?
10
  
11
  
12
  double a1 = 12, a2 = 17;
13
  createWrapper(a1,a2);
14
  //double ergebnis;
15
  //createWrapper(12,13);
16
  cout << Add(wrapper,a1,a2) <<"--------" << endl;;
17
  cout << Subst(wrapper,a1,a2)<< "+++++++" << endl;
18
  cout << Mult(wrapper,a1,a2)<< "########" << endl;
19
  //Add(wrapper,12,13);
20
  getchar();
21
  return 0;
22
}

 Wie soll ich meinen struct initialisieren?
 Hier in der Dummy Projekt könnte mit 0 initialisiert werden, aber was 
wäre der richtige vorgehen?

von Daniel A. (daniel-a)


Lesenswert?

1
  Wrapper wrapper = {};
2
3
  double a1 = 12, a2 = 17;
4
  wrapper = createWrapper(a1,a2);
5
  ...

PS: Wozu dieses struct Wrapper?

: Bearbeitet durch User
von Daniel (Gast)


Lesenswert?

Daniel A. schrieb:
> PS: Wozu dieses struct Wrapper?

Struct Wrapper dient darum MyClass als ReferenceObject zu haben

von Daniel (Gast)


Lesenswert?

Für diesem dummyProjekt funktioniert alles.

In meinem richtigen Projekt bekomme ich einen Unhandled exception?

von Klaus W. (mfgkw)


Lesenswert?

Daniel schrieb:
> In meinem richtigen Projekt bekomme ich einen Unhandled exception?

Dann mach im Wrapper doch um alles C++, das du aufrufst, ein try rum und 
fange die Ausnahmen.

von physiker (Gast)


Lesenswert?

Hört sich so an, als hättest Du in dem Wrapper für die richtige Library 
irgendwo in der Ansteuerung einen Fehler drin (oder die ist kaputt und 
schmeisst immer ne exception und wird in dem C++ basierten Hauptprogramm 
sonst immer abgefangen).

von Daniel (Gast)


Lesenswert?

Ohne der Wrapper funktioniert alles und zwar auf C++ ebene.

von fry (Gast)


Lesenswert?

Hi,
steht dir eigentlich der Quellcode von der HID.dll zur Verfügung? 
Probiere lieber diese direkt mit deinem wrapper anzusprechen.
Alternativ guck in den QT,c++ code nach dem header für die hid.DLL und 
was das c++ Programm an Parametern an die einzelnen Funktionen übergibt.

Dein funktionierendes Beispiel schreibst du dann einfach Funktion für 
Funktion um. Datentypen bei einer einfachen Ansteuerung musst du 
bestimmt nicht umkopieren, hier gehts ja nur um eine einfache 
Ansteuerung, wahrscheinlich werden maximal ein paar arrays kopiert 
werden müssen.

Ich kann mir gut vorstellen, dass in der hid.DLL nur die Ansteuerung für 
den Port implementiert ist. Such in deinem qt c++ nach Funktionen welche 
dein Gerät initialisieren, Daten sendet (bestimmt ein eigenes Protokoll 
mit CRC), die Daten empfangen und CRC prüft, Verbindung mit Gerät 
trennt.

von Daniel (Gast)


Lesenswert?

fry schrieb:
> steht dir eigentlich der Quellcode von der HID.dll zur Verfügung?
@Leider nein

fry schrieb:
> Such in deinem qt c++ nach Funktionen welche
> dein Gerät initialisieren, Daten sendet (bestimmt ein eigenes Protokoll
> mit CRC), die Daten empfangen und CRC prüft, Verbindung mit Gerät
> trennt.

Genau das habe ich als erst versucht aber leider ich bekomme stets einen 
Unhandled exception.

Ich habe in meinem C++ Quellencode einen Try {}Ausnahme angehängt um die 
Exception abzufangen aber es scheint das Problem noch tiefer.
Ich muss der Code (C++) noch weiteruntersuchen.

Hat jemenden so einen Projekt(C++, Qt) gehabt und für ihm einen Wrapper 
geschrieben?

Danke für den Feadback

von fry (Gast)


Lesenswert?

Such in dem QT Programm mal nach dem header für die hid.dll
Probier diese in einem neuen Programm anzusprechen.
Die Anleitung hier ist ziemlich gut: 
https://msdn.microsoft.com/en-us/library/ms810279.aspx

Dann schreib, ob du beim aufrufen der Funktionen noch immer Exceptions 
bekommst.

von Daniel (Gast)


Lesenswert?

Hallo Zusammen,

Das HID class.dll wird schon geladen und ich kann die Methoden der HID 
class.dll aufrufen so weit so gut.

Nun habe ich festgestellt, dass meinen Struct (in echten Projekt) gleich 
0 ist, was nicht richtig ist.
Ich glaube in meine Funktion createWrapper ist was faul.

von Daniel (Gast)


Lesenswert?

So sieht es meine Ursprüngliche Objekt aus:

Original Class:
1
class MyClass : public QObject
2
{
3
  Q_OBJECT
4
5
public:
6
  MYCLASS_EXPORT MyClass(bool boSimulate_p, QString &strFileSettings_p=QString("settingsFile.ini")); // settingsFile ist eine ini File und bestimmte Einstellung zu speichern und wieder aufzurufen
7
  MYCLASS_EXPORT ~MyClass();
8
  ....
9
}

C_Wrapper (für MyClass):

Header File
1
#ifndef _C_DLL_EFILIBWRAPPER_H_
2
#define _C_DLL_EFILIBWRAPPER_H_
3
4
/* building a DLL */
5
6
#define DLLIMPORT __declspec (dllexport)
7
8
#ifdef __cplusplus
9
   extern "C" { /* using a C++ compiler */
10
#endif
11
12
      typedef struct MYCLASSWrapper
13
    {
14
      void *C; 
15
    }MYCLASSWrapper;
16
17
    DLLIMPORT MYCLASSWrapper create_MyClass(bool boSimulate_p);
18
    DLLIMPORT MYCLASSWrapper create_MyClassWithSettingsFile(bool boSimulate_p, const char *strFileSettings_p);
19
20
    DLLIMPORT void destory_MYCLASSWrapper(MYCLASSWrapper LV_ref_MyClass);
21
    .....
22
      #ifdef __cplusplus
23
    }
24
#endif
25
#endif

// Cpp File (C_Wrapper (für MyClass):)
1
DLLIMPORT MYCLASSWrapper create_MyClass(bool boSimulate_p)
2
{
3
  const char *strFileSettings_p = "settings.ini";
4
  return create_MyClassWithSettingsFile(boSimulate_p,strFileSettings_p);
5
}
6
7
DLLIMPORT MYCLASSWrapper create_MyClassWithSettingsFile(bool boSimulate_p, const char *strFileSettings_p)
8
{
9
10
  MYCLASSWrapper MyClassWrapper = {static_cast<void*>(new MyClass(boSimulate_p,QString::QString(strFileSettings_p)))};
11
  
12
  return MyClassWrapper; 
13
}

von Karl H. (kbuchegg)


Lesenswert?

Daniel schrieb:

> Ich glaube in meine Funktion createWrapper ist was faul.

Wenn du das beim Testen auch so gemacht hast
1
int _tmain(int argc, _TCHAR* argv[])
2
{
3
  Wrapper wrapper = {}; // Wie soll ich meinen struct initialisieren ?
4
  
5
  
6
  double a1 = 12, a2 = 17;
7
  createWrapper(a1,a2);
dann sicherlich.

Du kriegst von createWrapper ein Wrapper-Objekt zurück. Damit musst du 
natürlich auch was machen. Zb dem wrapper Objekt zuweisen
1
....
2
  wrapper = createWrapper( a1, a2 );

und erst dann kannst du dieses Proxy Objekt wieder in die Funktionen zur 
Benutzung der DLL reinstecken.

Ansonsten: wenn sonst nichts hilft:
In der Zwischenschicht ein File aufmachen und alle aufgerufenen 
Funktionen schreiben eine Meldung samt Auflistung der Funktionsparameter 
rein. Dann kann man zumindest nachvollziehen, welche Aufrufe in welcher 
Reihenfolge getätigt werden, welche Argumente vom Aufrufer übergeben 
wurden und den Returnwert aus den Tiefen des CPP Teiles kann man auch 
noch ins File schreiben.

Und dann sieht man weiter, wenn man da mit dem Debugger nicht ran kann.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Wieviele derartige Wrapper Objekte brauchst du denn?

Da du erwähnt hast, dass es sich dabei um eine Kommunikation mit einem 
PIC handelt, wird es wohl nur ein einziges derartiges Objekt geben.
In diesem Fall brauchst du das auch nicht über die DLL-Grenzen zu 
exportieren, sondern die C++-Zwischenschicht hält sich dieses als 
Variable bei sich. Dann muss man auch nicht dauernd rumcasten.

Frei nach dem Muster
1
// DLL_Test_Labview.cpp : Defines the exported functions for the DLL application.
2
//
3
4
#include "stdafx.h"
5
#include "MyClass.h"
6
#include "C_DllWrapper.h"
7
8
static MyClass* pImpl = NULL;
9
10
DLLIMPORT void createWrapper(double a, double b)
11
{
12
  delete pImpl;
13
  pImpl = new MyClass(a,b);
14
}
15
16
DLLIMPORT void destoryWrapper(void)
17
{
18
  delete pImpl;
19
  pImpl = NULL;
20
}
21
22
DLLIMPORT double Add(double a, double b)
23
{
24
  if( pImpl )
25
    return pImpl->Add( a, b );
26
27
  return 0.0;
28
}
29
....

Für die Return Werte könntest du dir noch was einfallen lassen, zb ein 
paar Fehlercodes, wenn versucht wird mit einem NULL Pointer zu 
operieren.

: Bearbeitet durch User
von Daniel (Gast)


Lesenswert?

Hi alle zusammen,

Ich bin mittlerweile weiter gekommen.
Nun hakt in eine Sache und zwar:
eine Methode von meinem C_Wrapper hat als Rückgabeparameter eine Klasse 
Bclass .
nehmen wir einen Beispiel:

Die Methode sieht so aus:
1
Bclass Measure(MYCLASSWrapper LV_ref_MyClass);
Bclass ist wie folgende definiert :
1
class Bclass 
2
{
3
  public:
4
  Bclass();
5
  Bclass(Sclass * pSclass);
6
  Bclass(const Bclass *e) ;    // CopyConstructor
7
  {
8
    s1 = e.s1;
9
    s2 =e.s2;
10
    .....
11
  }
12
  virtual ~Bclass(){}
13
  .....
14
15
};

Sclass ist wie folgende definiert:
1
class Sclass: public Aclass, public Eclass, public Dclass
2
{
3
....
4
5
};

Meine Frage ist :wie soll ich meine Wrapper für dieses Funktion "Bclass 
Measure(MYCLASSWrapper LV_ref_MyClass)"  schreiben?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Daniel schrieb:
> eine Methode von meinem C_Wrapper hat als Rückgabeparameter eine Klasse
> Bclass .

Das ist nur dann sinnvoll, wenn dieser Rückgabe"parameter" außerhalb 
Deines Wrappers (d.h. in Labview) benötigt wird.

Ist das der Fall? Wozu ist dieser Rückgabe"parameter" da?

von Daniel (Gast)


Lesenswert?

Rufus Τ. F. schrieb:
> Das ist nur dann sinnvoll, wenn dieser Rückgabe"parameter" außerhalb
> Deines Wrappers (d.h. in Labview) benötigt wird.
>
> Ist das der Fall?
Ja
 >Wozu ist dieser Rückgabe"parameter" da?

Diese Rückgabe ist da um das Objeckt der von einen andere Klasse erzeugt 
wird weiterzuberechnen.

von physiker (Gast)


Lesenswert?

Daniel schrieb:
> Diese Rückgabe ist da um das Objekt der von einen andere Klasse erzeugt
> wird weiterzuberechnen.

Dann musst die doch nicht exponieren, oder? Mach die Berechnung 
innerhalb des Wrappers und gib nur das Ergebnis zurück, z.B. als struct.

von physiker (Gast)


Lesenswert?

Allgemein ist es schwierig zu beurteilen was genau in Deinem Fall Sinn 
ergibt, da wir uns nur über Platzhalter unterhalten und wir nicht genau 
wissen was da passiert. Du solltest vielleicht versuchen es so einfach 
wie möglich zu halten, d.h. überleg Dir welches Minimum an Informationen 
Du in deinen Wrapper stecken mußt und was an Informationen Du dann in 
dem Labview Teil dann wirklich verarbeiten mußt. Entsprechend bastelst 
Du Dir C Funktionen zusammen die Datentypen die C kennt entgegennehmen 
und wieder zurück geben. Wenn Du irgendwelche Objekte an andere 
übergeben mußt, machst Du das innerhalb des Wrappers, z.B. innerhalb 
einer Funktion
struct_type measure_and_calculate() oder indem Du das Objekt innerhalb 
des Wrappers zwischenspeicherst und nacheinander eine measure und 
calculate Funktion aufrufst.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Daniel schrieb:
> Diese Rückgabe ist da um das Objeckt der von einen andere Klasse erzeugt
> wird weiterzuberechnen.

Das bedeutet, das Ding wird weiteren Funktionen Deiner DLL übergeben, 
die von LabView aufgerufen werden?

Wenn das so ist: Mach da 'nen opaken Pointer draus. LabView selbst kann 
mit dem Ding nichts anfangen.

von Daniel (Gast)


Lesenswert?

Rufus Τ. F. schrieb:
> Das bedeutet, das Ding wird weiteren Funktionen Deiner DLL übergeben,
> die von LabView aufgerufen werden?

Jaein
Die RückgabeParameter brauche ich die nur zu darstellen.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Daniel schrieb:
> Die RückgabeParameter brauche ich die nur zu darstellen.

Ich hab's jetzt dreimal gelesen.

Hä?

von physiker (Gast)


Lesenswert?

Das ganze ist natürlich ein Herumgerate, da es an konkreten 
Informationen fehlt, Bezeichnungen wie Objekt und Klasse wild 
durcheinander geworfen werfen und das ganze ist mit sprachlichen Mängeln 
gewürzt, aber:

Was weiter verarbeitet wird ist ein Objekt vom Typ Sclass, wobei dieses 
Objekt durch die Methode Bclass Measure(MYCLASSWrapper LV_ref_MyClass) 
über den Konstruktor an ein Objekt vom Typ Bclass übergeben wird. Bclass 
hat vermutlich irgendwelche Getter die von Daniel nicht gezeigt wurden, 
um Einzelwerte, Arrays oder sonstwas für ("brauche ich die nur zu 
darstellen.") die Darstellung in Labview zu extrahieren. Wenn ich das so 
richtig verstanden habe, dann müssen innerhalb des Wrappers, in der 
Funktion ...Measure... die entsprechenden Getter aufgerufen und die 
Resultate in C Datentypen kopiert werden, die dann z.B. als struct als 
Rückgabewert benutzt werden (oder über einen zusätzlichen Parameter).

von Daniel (Gast)


Lesenswert?

physiker schrieb:
> Was weiter verarbeitet wird ist ein Objekt vom Typ Sclass, wobei dieses
> Objekt durch die Methode Bclass Measure(MYCLASSWrapper LV_ref_MyClass)
> über den Konstruktor an ein Objekt vom Typ Bclass übergeben wird. Bclass
> hat vermutlich irgendwelche Getter die von Daniel nicht gezeigt wurden,
> um Einzelwerte, Arrays oder sonstwas für ("brauche ich die nur zu
> darstellen.") die Darstellung in Labview zu extrahieren. Wenn ich das so
> richtig verstanden habe, dann müssen innerhalb des Wrappers, in der
> Funktion ...Measure... die entsprechenden Getter aufgerufen und die
> Resultate in C Datentypen kopiert werden, die dann z.B. als struct als
> Rückgabewert benutzt werden (oder über einen zusätzlichen Parameter).

Du hast genau auf dem Punkt gebracht. I am Sorry für die Sprachlichen 
Mängeln.
Es ist genau das was ich auch getan habe.

von Daniel (Gast)


Lesenswert?

Ich habe es folgende getan:

In der C_Wrapper (HeaderFile)
1
 //Bclass Measure(MYCLASSWrapper LV_ref_MyClass)  zu BHelpWrapper Measure(MYCLASSWrapper LV_ref_MyClass) angepasst
2
3
 BHelpWrapper Measure(MYCLASSWrapper LV_ref_MyClass) ;
4
 struct BHelpWrapper
5
 {
6
  const char* s1;
7
  const char* s2;
8
    const char* s3;
9
.......  
10
 };
11
 
12
 ...

 in der Cpp C_Wrapper:

1
#include "BClass.h"
2
....
3
4
 DLLIMPORT BHelpWrapper Measure(MYCLASSWrapper LV_ref_MyClass) 
5
 {
6
  BClass bclass;
7
  BHelpWrapper bhelpWrapper;
8
  ....
9
  bhelpWrapper.s1 = bclass .strgets1().toStdString().c_str();
10
  bhelpWrapper.s2 = bclass .strgets2().toStdString().c_str();
11
  
12
  ......
13
  
14
  // hier ist eingetlich mein Problem 
15
  // Rückgabeparameter muss eine Struct (laut Deklaration)
16
  // aber dann passiert es nichts in der Wrapper, da ich eine einen Rückgabeparamter von Typ BClass brauche
17
 }

 oder liege ich falsch ?
 Keine Ahnig

von Klaus W. (mfgkw)


Lesenswert?

Daniel schrieb:
> Keine Ahnig

ich auch nicht.
Ehrlich gesagt habe ich keinen Schimmer, worum es jetzt noch geht.
Und auch keine Lust, aus dem Gestammel etwas zu raten.

von Daniel (Gast)


Lesenswert?

Hallo alle zusammen,

es hat sich erledigt.
Danke für die Unterstützung.
Jetzt muss ich noch alle Mögliche Exception abfangen, dann das DLL in 
Labview integrieren.

von Daniel (Gast)


Lesenswert?

Hallo zusammen,

ich habe es noch einen kurze Frage:
Um das Board (PIC18f4550) mit Labview anzusprechen bzw. das Datenverkehr 
einwandfrei laufen, muss ich in Labview NI-VISA Driver Wizard was 
einstellen?

Bitte seh links
http://www.ni.com/tutorial/4478/de/


Danke

von Daniel (Gast)


Lesenswert?

Hallo zusammen,

ich habe eine Frage:
Ist das Möglich der DLL mit Hilfe des Debuggers (Visual Studio ebene) 
auf Fehler zu untersuchen?
Wenn ja wie soll ich den Visual Studio einrichten?

Danke in voraus

von Daniel A. (daniel-a)


Lesenswert?

Zu Visual Studio kann ich wenig sagen, aber mit gdb sollte es gehen. 
Einfach "gdb programmWelcheLibVerwendet" und dann breakpoints auf die 
libraryfunktionen setzen.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Daniel schrieb:
> Ist das Möglich der DLL mit Hilfe des Debuggers (Visual Studio ebene)
> auf Fehler zu untersuchen?

Natürlich. Dafür ist das da.

Eine Möglichkeit: Programm aufrufen, das Deine DLL verwendet - in Visual 
Studio "Debug - Attach to Process" ausführen.

von Daniel (Gast)


Lesenswert?

Rufus Τ. F. schrieb:
> in Visual
> Studio "Debug - Attach to Process" ausführen.
Wie komme ich hin?
bzw. wo finde ich das in Visual Studio?

Danke

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Daniel schrieb:
> bzw. wo finde ich das in Visual Studio?

Oben im Fenster gibt es ein Menü. Da steht "Debug". Und einer der Punkte 
in dem sich nach Klicken auf "Debug" öffnenden Menü heißt "Attach to 
Process".

von Daniel (Gast)


Lesenswert?

Hallo Zusammen,


Problematik:

In der C_wrapper habe ich folgende:
1
....
2
struct MyStruct
3
{
4
 double  wert1;
5
 double wert2;
6
 double wert3;
7
.....
8
9
10
11
12
}; // Dieses struct beinhaltet sehr viel Messwerte.
13
14
//Funktion 
15
 MYStruct DefaultMeasure(...);
16
...
 --> Diese Funktion hat als Rückgabeparameter "MYStruct" und das in 
Labview zu interfacen ist nicht so einfach.
 Meine Frage: wie soll ich das ambesten vorgehen?
 Soll ich das in eine extra HilfFunktion shreiben und dann was habe ich 
davon.
 Dieses Werte möchte ich in Labview (GUI) darstellen

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Deine Struktur scheint durch ein Array ersetzbar zu sein, wenn da 
tatsächlich nur double-Werte drinstehen.

Ansonsten wirst Du Dir ansehen müssen, auf welche Art und Weise LabView 
mit komplexen Datentypen umgeht und Deinen Wrapper so anpassen, daß er 
zwischen den beiden Sichtweisen (Deiner und der von Labview) hin- und 
her-übersetzt.

von Daniel (Gast)


Lesenswert?

Rufus Τ. F. schrieb:
> Deine Struktur scheint durch ein Array ersetzbar zu sein, wenn da
> tatsächlich nur double-Werte drinstehen.

Die struct beinhaltet unterschiedliche Datentypen

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Dann natürlich nicht. Das aber zeigt Dein Ausschnitt nicht.

von Daniel (Gast)


Lesenswert?

Rufus Τ. F. schrieb:
> Dann natürlich nicht. Das aber zeigt Dein Ausschnitt nicht.

Ja das Stimmt Sorry

von Daniel (Gast)


Lesenswert?

Rufus Τ. F. schrieb:
> Ansonsten wirst Du Dir ansehen müssen, auf welche Art und Weise LabView
> mit komplexen Datentypen umgeht und Deinen Wrapper so anpassen, daß er
> zwischen den beiden Sichtweisen (Deiner und der von Labview) hin- und
> her-übersetzt

Sorry muss noch mal fragen:

Gibt es keinen anderen Weg, der etwas einfacher ist?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Ich kenne und nutze LabView nicht.

Kann das mit Arrays umgehen? Gibt es einen Grund, warum Deine Struktur 
unterschiedliche Datentypen enthält? Muss auf jedes dieser 
Strukturelemente aus LabView heraus zugegriffen werden können?

von Daniel (Gast)


Lesenswert?

Rufus Τ. F. schrieb:
> Ich kenne und nutze LabView nicht.
>
> Kann das mit Arrays umgehen?
Ja
> Gibt es einen Grund, warum Deine Struktur unterschiedliche Datentypen >enthält?
Ja
>Muss auf jedes dieser Strukturelemente aus LabView heraus zugegriffen >werden 
können?
Nein
Diese werte sind nur auf Labview darzustellen, damit es festgestellt 
werden, ob was schief bei der Messung gelaufen ist oder nicht.
Dieses Daten werden immer aktualisiert sobald eine Messung durchgeführt 
ist.

von physiker (Gast)


Lesenswert?

Daniel schrieb:
>>Muss auf jedes dieser Strukturelemente aus LabView heraus zugegriffen >werden
> können?
> Nein
> Diese werte sind nur auf Labview darzustellen, damit es festgestellt
> werden, ob was schief bei der Messung gelaufen ist oder nicht.

Das ist doch ein "Zugriff", was denn sonst. Entweder Du schaust Dir an 
wie man ein struct in LabView weiterverarbeitet (cluster... hat eine 
schnelle Google Suche ergeben) oder Du teilst es in zig Arrays auf und 
gibts die separat zurück.

von Daniel (Gast)


Lesenswert?

Daniel schrieb:
>
> ich habe einen Dummy Projekt (C++) "um DLL zu erstellen" erstellt und
> dafür einen C_Wrapper geschrieben:
>
> Myclass.h#pragma once
> //#include <QString>
> class MyClass
> {
> public:
>   MyClass(double, double);
>   ~MyClass();
>   double Add(double,double );
>   double Subst(double, double);
>   double Mult(double, double);
>   double Divid(double, double);
>   bool Vergleich(double,double);
>   long Avg_num(float *, long, float *);
>   unsigned int NumInteger(char * inputString);
>   //QString GibEinString(double, double);
> private:
>   double m_a, m_b;
> };
> MyClass.cpp
>
> #include "stdafx.h"
> #include "MyClass.h"
>
> MyClass::MyClass(double a,double b)
> {
>   this->m_a = a;
>   this->m_b = b;
> }
>
> MyClass::~MyClass(){ }
>
> double MyClass::Add(double a, double b)
> {
>   return a+=b;
> }
> double MyClass::Mult(double a, double b)
> {
>   return a*=b;
> }
> double MyClass::Subst(double a, double b)
> {
>   return b-=a;
> }
> double MyClass::Divid(double a, double b)
> {
>   return (b / a);
> }
> bool MyClass::Vergleich(double a,double b)
> {
>   if(a>=b) return true;
>   else return false;
> }
>
> long MyClass::Avg_num(float *a, long size, float *avg)
> {
>   //avg_num ermittelt den einfachen Durchschnitt eines Arrays
> numerischer Werte
>   float sum = 0;
>   if(a != NULL)
>     {
>         for(int i=0;i < size; i++)
>         sum = sum + a[i];
>     }
>     else
>         return (1);
>     *avg = sum / size;
>     return (0);
> }
> unsigned int MyClass::NumInteger(char * inputString)
> {
>   int lastDigit = 0;
>     int numberOfNumbers = 0;
>     int stringSize;
>
>     stringSize = strlen(inputString);
>     for(int i = 0; i < stringSize; i++)
>     {
>         if (!lastDigit && isdigit(inputString[i]))
>             numberOfNumbers++;
>         lastDigit = isdigit(inputString[i]);
>     }
>   //numIntegers bestimmt die Anzahl der Integer-Werte in einem String
>     return numberOfNumbers;
>
> }
>
> C_Wrapper.h#pragma once
> #define DLLIMPORT __declspec (dllexport)
> #ifdef __cplusplus
> extern "C" {
> #endif
>
> typedef struct Wrapper
>   {
>     void *MYClass;
>   }Wrapper;
>
>   DLLIMPORT Wrapper createWrapper(double a, double b);
>   DLLIMPORT void destoryWrapper(Wrapper LV_ref);
>
>   DLLIMPORT double Add(Wrapper LV_ref, double a, double b);
>   DLLIMPORT double Subst(Wrapper LV_ref ,double a, double b);
>   DLLIMPORT double Mult(Wrapper LV_ref, double a, double b);
>   DLLIMPORT double Divid(Wrapper LV_ref, double a, double b);
>   DLLIMPORT bool Vergleich(Wrapper LV_ref, double a, double b);
>   DLLIMPORT long Avg_num(Wrapper LV_ref,float *a, long size, float *
> avg);
>   DLLIMPORT unsigned int NumInteger(Wrapper LV_ref, char * inputString);
>
> #ifdef __cplusplus
> }
> #endif
>
> C_Wrapper.cpp// DLL_Test_Labview.cpp : Defines the exported functions
> for the DLL application.
> //
>
> #include "stdafx.h"
> #include "MyClass.h"
> #include "C_DllWrapper.h"
>
> DLLIMPORT Wrapper createWrapper(double a, double b)
> {
>   Wrapper wrapper = {static_cast<void*>(new MyClass(a,b))};
>   return wrapper;
> }
>
> DLLIMPORT void destoryWrapper(Wrapper LV_ref)
> {
>   MyClass *myClass = static_cast<MyClass*>(LV_ref.MYClass);
>   delete myClass;
> }
> DLLIMPORT double Add(Wrapper LV_ref, double a, double b)
> {
>   MyClass *myClass = static_cast<MyClass*>(LV_ref.MYClass);
>   return myClass->Add(a, b);
> }
>
> DLLIMPORT double Mult(Wrapper LV_ref, double a, double b)
> {
>   MyClass *myClass = static_cast<MyClass*>(LV_ref.MYClass);
>   return myClass->Mult(a, b);
> }
>
> DLLIMPORT double Subst(Wrapper LV_ref, double a, double b)
> {
>   MyClass *myClass = static_cast<MyClass*>(LV_ref.MYClass);
>   return myClass->Subst(a, b);
> }
>
> DLLIMPORT double Divid(Wrapper LV_ref, double a, double b)
> {
>   MyClass *myClass = static_cast<MyClass*>(LV_ref.MYClass);
>   return myClass->Divid(a, b);
> }
> DLLIMPORT bool Vergleich(Wrapper LV_ref, double a, double b)
> {
>   MyClass *myClass = static_cast<MyClass*>(LV_ref.MYClass);
>   return myClass->Vergleich(a,b);
> }
> DLLIMPORT long Avg_num(Wrapper LV_ref,float *a, long size, float * avg)
> {
>   MyClass *myClass = static_cast<MyClass*>(LV_ref.MYClass);
>   return myClass->Avg_num(a,size,avg);
>
> }
> DLLIMPORT unsigned int NumInteger(Wrapper LV_ref, char * inputString)
> {
>   MyClass *myClass = static_cast<MyClass*>(LV_ref.MYClass);
>   return myClass->NumInteger(inputString);
> }


Hallo Zusammen,

Zurück zu diesem Dummy Projekt

Ich habe es die DLL File mit der entsprechenden Header File in Labview 
importiert.
Es funktioniert zwar einwandfrei aber mir im nachenein sind mehrere 
Sachen Unklar geblieben.

1)
1
DLLIMPORT Wrapper createWrapper(double a, double b)
2
{
3
  Wrapper wrapper = {static_cast<void*>(new MyClass(a,b))};
4
  return wrapper;
5
}

Wie soll ich der
1
  void *MYClass
 Pointer in Labview initialisieren?

2)Bei der restlichen Funktionen :
1
DLLIMPORT void destoryWrapper(Wrapper LV_ref);
2
3
DLLIMPORT double Add(Wrapper LV_ref, double a, double b);
4
DLLIMPORT double Subst(Wrapper LV_ref ,double a, double b);
5
DLLIMPORT double Mult(Wrapper LV_ref, double a, double b);
6
DLLIMPORT double Divid(Wrapper LV_ref, double a, double b);
7
DLLIMPORT bool Vergleich(Wrapper LV_ref, double a, double b);
8
DLLIMPORT long Avg_num(Wrapper LV_ref,float *a, long size, float * avg);
9
DLLIMPORT unsigned int NumInteger(Wrapper LV_ref, char * inputString);

Wie soll ich auch hier:
1
  void *MYClass
 initialisieren?
und ob ich das auch bei allen tun muss?

Danke in voraus

von Daniel (Gast)


Angehängte Dateien:

Lesenswert?

Hallo alle zusammen:


mein Block Digramm für die
1
"DLLIMPORT Wrapper createWrapper(double a, double b)"
 sieht so aus (Seh bitte Anhang"createWrapper")

Die Einstellung der Library sieht so aus(Seh bitte Anhang"Library 
Einstellung").


Danke

von Daniel (Gast)


Angehängte Dateien:

Lesenswert?

sorry das ist der erste Anhang

von Daniel (Gast)


Lesenswert?

Ich stehe wirklich auf dem schlauch !!!!

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Was erwartest Du? Daß sich jemand hinsetzt und Deine reichlich 
zusammenhangslosen letzten Beiträge durchliest, nur um eine nicht 
gestellte Frage zu beantworten?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.