LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

How to link a wrapper DLL to the target DLL

I appreciate your help!

 

Question:

 

In my project, I need to deal with a hybrid programming of C++ and Labview. The C++ part has been encoded into a DLL, which aims to do a complex mathematics. The main function in the DLL has the following form:

 

                          float RateEqCalculate(class CLaserPulse *Pulse, class CMaterial *Material, class CThresh *ThreshPara, class CRateResults &r);

 

The four arguments are all of the class type. The first three arguments are used to input parameters to the function and the last one is used to record the process of computation. For example: class CLaserPulse is composed by several numerics and two functions as the following form:

class CLaserPulse
{
public:
 float fDuration;  

 float fWave;  
 float fNA;   

 float fRefrIndex;                                     // Refractive Index
 float fAbsCoeff;                                     // Absorption coefficient [1/m]

 CLaserPulse();
 virtual ~CLaserPulse();
 virtual double Shape(double dTime);       // gives Temporal Shape
 float SpotDiameter();                            // Calculate Spotdiameter

};

As in labview "class" cannot be accepted as an argument of the "Library Function Node" directly, a wrapper DLL is required to translate the "class" to the type labview can understand. The following link is a good illustration of this process. http://labviewwiki.org/DLL/shared_library Given the argument class CLaserPulse has been converted into the wrapper DLL by the method from the link, how can I later link this wrapper DLL to the target DLL. My understanding is like this:

 

                                                                                             Target DLL

                                                                                float RateEqCalculate(

  class CLaserPulse  ->   wrapper DLL       .........linking.........        class CLaserPulse,

  class CMaterial      ->   wrapper DLL       .........linking.........        class CMaterial,

  class CThresh        ->   wrapper DLL       .........linking.........        class CThresh ,

  class CRateResults  ->   wrapper DLL     .........linking.........        class CRateResults );

 

Am I right? Four wrapper DLL to four class type arguments?

 

Many thanks!!!

 

0 Kudos
Message 1 of 9
(5,402 Views)

Hi Kuo,

 

have to say that I have written a wrapper DLL, but I somehow used another way to do so (At least, it looks not so complicated like in the example :-)). 

 

What you need:

- Your DLL (which includes the classes)

- A .lib file (should be automatically created if you build the upper DLL)

- the header file including the class definitions.

 

What you now have to do is: Write (in a new DLL, wrapper-DLL) a function that can accept all parameters you need for your classes, like fDuration, fWave, FNa and so on.. it's important to use only types that LabView can handle (like double, integer, string, ...)

 

Now, in your Wrapper, you have to create a member of the class you like to use, for example CLaserPulse. Fill your class with all parameters you need (passed from LabView). Add to your project (if you are using Microsoft Visual C++) the .lib and the .h of your other DLL and compile it. It should be linked to your DLL. By LabView, you can now access the wrapper DLL.

 

A short example (not sure about notation, not tried in C++):

 

DLL you like to access:

 

typedef struct      //Complex Number Typedef, in header file

{

    double real;

    double imag;

} complex;

 

int calc(complex a)  // Function in your DLL LabView can't handle because of datatype complex

{

    //any code

}

 

 

WRAPPER-DLL:

 

int calc_wrap(double real, double  imag)

{

    //Build the complex datatype

   complex temp;

   temp.real=real;

   temp.imag=imag;

   return calc(temp);   //pass variable temp to your DLL, calculate value and return it to labview

}

 

Hope this helps,

 

Greetings

 

Christian


THINK G!! 😉
------------------------------------------------------------------------------------------------
Using LabView 2010 and 2011 on Mac and Win
Programming in Microsoft Visual C++ (Win), XCode (Mac)
Message 2 of 9
(5,362 Views)

You do not necessarily have to create seperate wrappers for each class. A class is the same as in standard C a struct as far as memory layout is concerned. So your parameters are simply pointers to a struct. Now you can't access the members of that struct from within LabVIEW directly but you can treat the pointer to the class as a pointer sized integer when passing it to the Call Library Node.

 

What you will quite likely have to do is writing some constructor and destructor wrappers for each of your classes and if you need to access methods of those classes or variable members you will also have to write a method wrapper for each method you want to use as well as an accessor function for each variable member you want to be able to access. So likely your wrapper library will contain a lot more functions than just one for each class. In fact because of the constructor/deconstructor you will need, you will need at least 2 functions per class.

 

Rolf Kalbermatter 

Message Edited by rolfk on 08-25-2009 12:16 PM
Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
Message 3 of 9
(5,357 Views)

I just come back from my holidays. I really appreciate your suggestions!! I will try it.

0 Kudos
Message 4 of 9
(5,283 Views)

I really like your penetrating explanation from the respects of memory layout.

I'll try it!

 

Thank you very much!

0 Kudos
Message 5 of 9
(5,275 Views)

Hello Rolf and Christian: 

Thank you for your suggestions! I'm now working on it. I appreciate your continuous help!! 

I'll briefly summarize my question here:

In the original DLL, which is compiled by VC++ 6.0 and named RateEquation.dll, three class types (CLaserPulse, CMaterial& CThresh) are inclueded to do parameter exchanges; one class type is designed to save the calculation results(CRateResults);one main function to do the calculation and save the results as following form:  

 float RateEqCalculate(class CLaserPulse*, class CMaterial*, class CThresh*, class CRateResults &r); 

My question now is the initialization of the struct type and the communication between this type with labview. 

I'll take class CMaterial as an example to show how I made it into wrapper DLL.Original class CMaterial is defined as following:

class CMaterial
{
public:
 float AbsorberGap;
 float BandGap;
 float CollTime;
 float ElDensity;
 float RefractiveIndex; 
 float AbsorptionCoeff;  
 float MoleculeMass;  
 float Density;  
 float HeatCapacity;  
 float HeatConductivity; 
 float TAmbient;  

 CMaterial();
 virtual ~CMaterial();
};

 

  In a wrapper dll it's like this: 

WrapperDll.h

 extern "C" { /*using a C compiler*/            //Using a C compiler to write the wrapper DLL
#endif
 

struct RATEEQUATION_API CMaterial{                  
  //Electronical properties
  float AbsorberGap;
  float BandGap;
  float CollTime;
  float ElDensity;
  //Optical properties
  float RefractiveIndex;
  float AbsorptionCoeff;
  //Other properties
  float MoleculeMass;
  float Density;
  float HeatCapacity;
  float HeatConductivity;
  float TAmbient;
 };
  typedef struct CMaterial CMaterial;                                             /* make the class opaque to the wrapper*/
 RATEEQUATION_API CMaterial* creat_CMaterial(void);          
 

RATEEQUATION_API void destroy_CMaterial(CMaterial* LV_ref);
#ifdef __cplusplus
}
#endif
  

 

WrapperDll.cpp

RATEEQUATION_API CMaterial* creat_CMaterial(void)

{

       return new CMaterial();                              

}

RATEEQUATION_API void destroy_CMaterial(CMaterial* LV_ref)

{

       delete LV_ref;

}

 In function creat_CMaterial(), one can see the constructor of class CMaterial is called. As struct type CMaterial has the same memory layout as class type CMaterial, so it’s safe and possible to return a class CMaterial* to struct CMaterial* and it’s initialized by the default values in the class constructor. Now I’m confused by how one communicates between labview and struct CMaterial. For example, if I would like to change the parameter _CMaterial-> BandGap=6.5eV to 8eV. How to make it?

My feeling is I need a cluster type from Labview as an input in the function creat_CMaterial:

                          CMaterial* creat_CMaterial(cluster_LV*)

Many thanks!

Message Edited by Kuo on 09-15-2009 09:56 AM
Message Edited by Kuo on 09-15-2009 09:59 AM
0 Kudos
Message 6 of 9
(5,207 Views)

No, I do not think that creating a C struct and treating it as C++ object pointer is going to work. The C++ compiler is free to arrange the variables in the class to some extend and also will include at least one vtable immediately at the start of the memory that the class structure defines.

 

This is one of the reasons that you can not mix and match C++ libraries between compilers since they will arrange the class members often differently in memory therefore causing crashes if you call a C++ class from code compiled in compiler X while the class was implemented in compiler y.

 

Rolf Kalbermatter

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
Message 7 of 9
(5,199 Views)

Hello Rolf:

 

I think I made a mistake in the message. The same C++ compiler is used when treating C++ class type as a C struct . Using extern "C" in the code is to make the function calls C calls instead of C++ calls. Following is a link to explain the wrapper dll method. http://labviewwiki.org/DLL/shared_library

 

Thanks

 

Kuo

0 Kudos
Message 8 of 9
(5,172 Views)

Even when using the same compiler you will not be able to treat a C++ class as C struct. The reason is that you can NOT easily deduce the exact memory layout from a C++ class declaration and therefore can't create a struct easily that would match that class layout.

 

The wiki page however is correct. Note that in there the object pointer is only referenced in the function wrappers, and while those functions should be prototyped with the extern C keyword to avoid name decoration and other nastyness, the code for those wrappers will be compiled by the C++ compiler so it knows how to access the class members properly.

 

Rolf Kalbermatter

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 9 of 9
(5,158 Views)