C_Wrapper



  • Hallo Zusammen,

    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 Header

    #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);
    }
    

    --> 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 wollte ich das fast das gleiche testen aber dieses Mal mit dem echten projekt.

    Meine echten Objeckt sieht wie folgende aus:
    Original Class:

    class MyClass : public QObject
    {
      Q_OBJECT
    
    public:
      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
      MYCLASS_EXPORT ~MyClass();
      ....
    }
    

    C_Wrapper (für MyClass):

    Header File

    #ifndef _C_DLL_EFILIBWRAPPER_H_
    #define _C_DLL_EFILIBWRAPPER_H_
    
    /* building a DLL */
    
    #define DLLIMPORT __declspec (dllexport)
    
    #ifdef __cplusplus
       extern "C" { /* using a C++ compiler */
    #endif
    
          typedef struct MYCLASSWrapper
        {
          void *C; 
        }MYCLASSWrapper;
    
        DLLIMPORT MYCLASSWrapper create_MyClass(bool boSimulate_p);
        DLLIMPORT MYCLASSWrapper create_MyClassWithSettingsFile(bool boSimulate_p, const char *strFileSettings_p);
    
        DLLIMPORT void destory_MYCLASSWrapper(MYCLASSWrapper LV_ref_MyClass);
        .....
          #ifdef __cplusplus
        }
    #endif
    #endif
    

    // Cpp File (C_Wrapper (für MyClass)):

    DLLIMPORT MYCLASSWrapper create_MyClass(bool boSimulate_p)
    {
      const char *strFileSettings_p = "settings.ini";
      return create_MyClassWithSettingsFile(boSimulate_p,strFileSettings_p);
    }
    
    DLLIMPORT MYCLASSWrapper create_MyClassWithSettingsFile(bool boSimulate_p, const char *strFileSettings_p)
    {
    
      MYCLASSWrapper MyClassWrapper = {static_cast<void*>(new MyClass(boSimulate_p,QString::QString(strFileSettings_p)))};
    
      return MyClassWrapper; 
    }
    

    Nun habe ich festgestellt, dass meinen Struct (in echten Projekt) gleich
    0 ist, was nicht richtig ist.

    Was mache ich denn falsch?



  • MarcoGast schrieb:

    Nun habe ich festgestellt, dass meinen Struct (in echten Projekt) gleich
    0 ist, was nicht richtig ist.

    Was mache ich denn falsch?

    Du irgendwie irgendwo irgendwas festgestellt, aber keinen Code geliefert, der den Fehler reproduziert. Da wird dir wohl niemand helfen können.

    Benutze einen Debugger, überprüfe, wann es nach create_MyClassWithSettingsFile schief geht.
    Wird vielleicht eine Exception geworfen und ignoriert?



  • 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:

    Bclass Measure(MYCLASSWrapper LV_ref_MyClass);
    

    Bclass ist wie folgende definiert :

    class Bclass 
    {
    	public:
    	Bclass();
    	Bclass(Sclass * pSclass);
    	Bclass(const Bclass *e) ;    // CopyConstructor
    	{
    		s1 = e.s1;
    		s2 =e.s2;
    		.....
    	}
    	virtual ~Bclass(){}
    	.....
    
    };
    

    Sclass ist wie folgende definiert:

    class Sclass: public Aclass, public Eclass, public Dclass
    {
    
    };
    

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



  • Wenn du C-Wrapper benötigst, dann mußt du für alle deine Klassen Wrapper erstellen, also auch eine Bclass_Wrapper:

    Bclass_Wrapper Measure(MYCLASSWrapper LV_ref_MyClass);
    

Anmelden zum Antworten