wrapper in c (quellcode ist C++ und QT)

Gast #4244767
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?
Gast #4244805
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.
Persönliche Seite #4244875
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.
Gast #4249221
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?
Gast #4250311
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?
Gast #4250809
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).
Gast #4251041
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.
Gast #4252157
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
Gast #4254910
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.
Gast #4255001
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
}
#4255743
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.
#4255746
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.
Gast #4256581
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?
Gast #4256619
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.
Gast #4256654
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.
Gast #4256984
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).
Gast #4257302
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.
Gast #4257310
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
Gast #4263389
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
Gast #4266407
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
Gast #4266516
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?
Gast #4266552
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.
Gast #4266587
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.
Gast #4268197
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren