Several source codes are collected here in three different categories: Starting with C++, Advanced and Using Qt. This home-page is created to be a repository of C++ source codes, that examines single C++ instructions to better understand how they work and how they can be used. This site in NOT designed to be a C++ Tutorial.
Contents:
gmake - Parallel execution of gmakeenvironment - Preparing the complete environment to work with C/C++ (gcc, eclipse,…).
const - Understanding const type variable declaration.
extern - Using global variables with extern.
if - Different forms to write an if statement.
String 2 Float - Tips to convert a string in float (double).
Type casting - Convert an expression of a given type into another type (cast).
Macros - Use of macros - #define.
Macros (2) - Preprocessor directives.
union - Dynamic types with unions.
Inheritance - Inheritance (specialization), public, private and protected.
Database:
gmake |
Parallel execution of gmake.
The following options are usefull
-j <number of processors>
-l <maximum load limit>
The example below starts gmake with maximum 4 processes, but befor the load average must be checked. If the CPU load exceeds 2.5 only one process will be started till the load average goes below the given limit.
gmake -j 4 -l 2.5
The ‘-l’ option with no following number removes the load limit, if one was given with a previous ‘-l’ option.
I normaly do not have problems with CPU load, so I do not use -l to limit the parallelization.
environment |
Preparing the complete environment to work with C/C++ (gcc, eclipse,…).
Working with linux you will need to install the packages listed in gcc.
Editor I use sometimes vi, sometimes Eclipse (see Ubuntu forum theme Eclipse or Eclipse), it is up to you. If you decide to use Eclipse so you need to have Java installed, who told that is easy, see Ubuntu forum theme Java.
I solve every thing with:
- download the eclipse file from Eclipse than
- expand it with tar,
- as root move to a general application path sudo mv,
- create a link to better access sudo ln,
- install C/C++ compiler (build-essential and kernel-headers) with sudo apt-get and
- install java also with sudo apt-get and
- create an icon in my Application menu.
$ tar xvfz eclipse-cpp-xxx-linux-gtk-xxx.tar.gz
$ sudo mv ./eclipse /opt
$ sudo ln -s /opt/eclipse/eclipse /usr/bin/eclipse
$ sudo apt-get install build-essential linux-headers-`uname -r`
$ sudo apt-get install openjdk-6-jre
const |
Understanding const type variable and function declaration.
Apply const in variables and pointers.
int main( int argc , char** argv ) { int a = 10; const int b = 15; //constant value a = 20; //legal //b = 20; //error int* test = new int(100); const int* c = new int(20); //pointed value is constant int* const d = new int(25); //pointer is constant c = test; //legal //d = test; //error //*c = a; //error *d = a; //legal return 0; }
Applying const in funcitons. A Function can have const denomination for it's return value and arguments. The const variables follow the same roles as described above.
Writing a class is possible to declare a const function to protect member objects against changes. It can be done writting const at the end of the function declaration, after closing the function argument brackets, in both prototype and definition. The reasons to use const functions are:
- to create a more efficient code due to compiler object compilation.
- to protect the class object members against changes. Useful on inheritances in OOP. Remark, Constructor and Destructor cannot be const for an obvious reason, they must be able to change class objects members.
- can overload with non-const functions. The compiler will decide the apropriate one depending on the object they are been applied to.
class student{ public: int numberOfClasses() const //function cannot change class objects { return noClasses; }; // legal const int noOfClasses() const; //function cannot change class objects and return a const type variable { return noClasses; }; //noClasses will be returned as const void addNewClass(); //function can change class objects { noClasses++; }; //legal //void cancelClass() const; //function cannot change class objects //{ noClasses--; }; //error private: int noClasses; }; int main( int argc , char** argv ) { student Antonio; int a = noOfClasses(); //error: the function returns a const const int b = noOfClasses(); //constant value. Ok! Antonio.addNewClass(); //Antonio.cancelClass(); return 0; }
extern |
Using global variables with extern.
I don't like to use global variables, but… none can say that will never use it.
The source code below I have in a file called main.cpp.
#include <iostream> using namespace std; void func1(void) { // test is not previously declared, comment out this line will let to // a compiler error. But as extern it will be ignored by // the compiler and the linker will check its existence. extern int test; test = 3; } int test; //defining test as global variable. void exemploExtern(void) { // variable test is declared previously (global variable), so // this line can be omited not generating a compiler error. // if the variable test exists in a different file so it must be // declared as extern. //extern int test; test = 2; cout << endl << "variable test = " << test; func1(); cout << endl << "variable test after func1() = " << test << endl; } int main() { //trabalho com variavel global 'extern' exemploExtern(); return 0; }
the command line above will compile and link the source code generating the application useExtern.
$ g++ -o useExtern main.cpp
Just start the application with
$ ./useExtern
variable test = 2
variable test after func1() = 3
if |
Different forms to write an if statement.
#include <iostream.h> int main( int argc , char** argv ) { int a = 10; int b = 15; cout<<"a = " << a << endl; cout<<"b = " << b << endl; //common way to write a if statement. if(a > b) cout << "a is bigger than b" << endl; else cout << "a is NOT bigger than b" << endl; //another way to write a if statement int c = (a > b)?a:b; cout<<"the maximal number between a and b is "<<c<<endl; //is also posible to use the above if statement and generate //multiplo commands inside the if int d = (a < b)? (cout<<"sum = a + b = "<<a+b<<endl, a): (cout<<"dif = a - b = "<<a-b<<endl, b); cout << "the smalest value between a and b is " << d << endl; //with more than one operation int calc = 0; int f = (a > b)? (calc=a+b, cout<<"sum=a+b="<<calc<<endl, a): (calc=a-b, cout<<"dif=a-b="<<calc<<endl, b); return 0; }
String 2 Float |
Tips to convert a string in float (double).
There are several ways to convert a string in number.
- Using stringstream, from sstream.h;
- atof, from stdlib.h;
- sscanf, from stdio.h;
- or converting each character according to the ASCII Table.
I recomend to use sscanf. It offers the possibility to convert strings based on a given mask. Another important point is the possibility to check for error.
Attention: sscanf can convert to float, if you need a double, a posterior cast must be done.
#include <cstdio> int main( void ) { char text[30] = "velocity = 65.5 km/h"; char variableName[30], unit[10]; float value; //three variables must be converted if (sscanf(text,"%s = %f %s", &variableName, &value, &unit) == 3) printf("All terms are converted.\n\n%s[%s] is equal to %f", variableName,unit,value); else printf("Not all terms or none are converted.\n"); }
Type Casting |
Convert an expression of a given type into another type.
Implicit conversion
automaticaly performed by copying a value to a compatible type without any type-cast operator. Such cast can let to precision loss and therefore treated as warning from some compilers. The example below shows an implicit cast from short to int.
short a=123; int b; b=a;
To make use of implicit cast in classes, an associated constructor must be implemented. For example:
class A{};
class B{ public: B(A a){} };
[[/code]]
Explicit conversion
use a cast operator making explicit the conversion. A spetial attention is necessary, when programming classes or using pointers to classes in conversions, to avoid runtime errors, see example in [1]. The example below shows two forms of explicit cast.
short a=123; int b; b= (int) a; // c-like cast notation b= int( a ); // functional notation
dynamic_cast
it helps to control conversions between classes and can only be used with pointers and references to objects.
class CBase { }; class CDerived: public CBase { }; CBase * pba = new CDerived; CBase * pbb = new CBase; CDerived * pd; pd = dynamic_cast<CDerived*>(pba); // ok: derived-to-base if (pd==0) cout << "Null pointer on first type-cast" << endl; pd = dynamic_cast<CDerived*>(pbb); // wrong: base-to-derived are not allowed if (pd==0) cout << "Null pointer on second type-cast" << endl;
Compatibility note: dynamic_cast requires the Run-Time Type Information (RTTI) to keep track of dynamic types. Make sure that this feature is enabled at the compiler.
static_cast
It can perform conversions between pointers to related classes, from the derived class to its base and from a base class to its derived. The overhead of the type-safety checks of dynamic_cast will not happen, but the programmer must ensure that the conversion is safe. It can also be used to perform non-pointer conversions.
class CBase {}; class CDerived: public CBase {}; CBase * a = new CDerived; CDerived * b = static_cast<CDerived*>(a);
reinterpret_cast
It converts any pointer type to any other pointer type, even of unrelated classes. It is a binary copy without check of the content pointed or the pointer type itself. Take care using it!!
const_cast
It converts constant into non-constant objects. It is usefull when passing a const variable to a function that expects a non-constant parameter.
// const_cast #include <iostream> using namespace std; void print (char * str) { cout << str << endl; } int main () { const char * c = "sample text"; print ( const_cast<char *> (c) ); return 0; }
typeid
It returns a reference to a constant object, identifiing it with the class name.
// typeid #include <iostream> #include <typeinfo> using namespace std; int main () { int * a,b; a=0; b=0; if (typeid(a) != typeid(b)) { cout << "a and b are of different types:\n"; cout << "a is: " << typeid(a).name() << '\n'; cout << "b is: " << typeid(b).name() << '\n'; } return 0; }
Macros |
Use of macros - #define.
There are several preprocessing directives, see [2]. Preprocessor directives are not program statements but directives for the preprocessor, in other words it will not be compiled, but used from a preprocessor to prepare the source according to developer definitions.
The most used are:
- #include, tells the preprocessor to treat the contents of a specified file as if those contents had appeared in the source program at the point where the directive appears.
- #define, used to create identifiers, constant variables, functions and also to rename funcitons/classes.
- #if defined, #ifdef, #ifndef, #if not defined, #elif, #else, #endif, test identifiers
Below some examples are presented.
Creating a new directive
#include <iostream> #define BRASIL // Creating an identifier void main(void) { #if defined BRASIL //test if the identifier is used. std::cout << "algum texto em Portugues."; #else std::cout << "some english text."; #endif }
Defining macros and constants with the /D compiler option has the same effect as using a #define preprocessing directive at the beginning of your file. Up to 30 macros can be defined with the /D option.
Defining constats
#define identifier replacement
The preprocessor will replace any occurrence of identifier in the rest of the code by replacement.
#include <iostream> #define PI 3.14159265359 // Creating a constant void main(void) { float angleInGrad = 30; std::cout << angleInGrad <<" grad, correspond to " << angleInGrad * PI / 180.0 << " rad"; }
Defining function makros
It is a function worked by the preprocessor and like the constant, the preprocessor will replace each occurrence of the function with the expression and its arguments.
#include <iostream> #include <cstdlib> // Macro to get a random integer with a specified range #define getrandom(min, max) ((rand()%(int)(((max) + 1)-(min)))+ (min)) void main(void) { std::cout << getrandom(11,16); }
Renaming elements
The preprocessor directive '#define' is also used to rename elements in the code like variables, function names or class names.
#include <iostream> #define BRASIL // Renaming functions void portugues(void) { std::cout << "algum texto em Portugues."; } void english(void) { std::cout << "some english text."; } #if defined BRASIL #define printMessage portugues #else #define printMessage english #endif void main(void) { printMessage(); }
Macros (2) |
Preprocessor directives.
There are standard macro names for all compilers. Some of them are taken from cplusplus - Preprocessor directives and listed below:
macro | value |
LINE | Integer value representing the current line in the source code file being compiled. |
FILE | A string literal containing the presumed name of the source file being compiled. |
DATE | A string literal in the form "Mmm dd yyyy" containing the date in which the compilation process began |
TIME | A string literal in the form "hh:mm:ss" containing the time at which the compilation process began. |
__cplusplus | An integer value. All C++ compilers have this constant defined to some value. If the compiler is fully compliant with the C++ standard its value is equal or greater than 199711L depending on the version of the standard they comply. |
Another reference for preprocessor definitions is [3],
A shell script to print out some preprocessor macros are available in [3] and can also be found here /download/defines.sh for download. No guarantee about the correctness of the macros is given.
An example is taken from Wikipedia - C preprocessor showing a self written debug macro.
#define dumpme(x, fmt) printf("%s:%u: %s=" fmt, __FILE__, __LINE__, #x, x) int some_function() { int foo; /* [a lot of complicated code goes here] */ dumpme(foo, "%d"); /* [more complicated code goes here] */ }
There are some ways to ask the compiler its standard preprocessor directives.
- GNU C Compiler
gcc -dM -E - < /dev/null
- HP-UX ansi C compiler
cc -v fred.c (where fred.c is a simple test file)
- SCO OpenServer C compiler
cc -## fred.c (where fred.c is a simple test file)
union |
Dynamic types with unions.
Union can be used to create dynamic types. The example below creates an union (valor) that can save float or int values, but not both. The union element must be explicit accessed, i.e. <union>.<variable inside union> .
Attention:
Union save only the last data and it is not able to tell you which type is already in use. There is also no execution error if you ask for a value type that is not in use by the union. The output from the example below exemplifies what I am saying. Use another variable to indicate which type you have in your union.
The source code below are saved in a file called main.cpp.
#include <iostream> using namespace std; void exemploUnion(void) { bool isInt; // used to control the active union type union valor { float x; int y; }; valor num; // valor can assume the float or the int value, not both. num.x= 3.0f; // save a float value isInt = false; cout << endl << "union value -> float = " << num.x << endl << "union value -> int = " << num.y << endl; num.y = 5; // save an integer value isInt = true; cout << endl << "union value -> float = " << num.x << endl << "union value -> int = " << num.y << endl; } int main() { exemploUnion(); return 0; }
Compile and link with:
$ g++ -o unionExample main.cpp
Executing:
$ ./unionExample
union value -> float = 3
union value -> int = 1077936128
union value -> float = 7.00649e-45
union value -> int = 5
Inheritance |
Inheritance (specialization), public, private and protected.
A class has function members and variables distributed in public, protected and private.
class Polygon { . . . }; class Rectangle: protected Polygon { . . . }; class Hexagon: protected Polygon { . . . };
Access | public | protected | private |
---|---|---|---|
members of the same class | yes | yes | yes |
members of derived classes | yes | yes | no |
not members | yes | no | no |
Basis class | public inheritance | protected inheritance | private inheritance |
---|---|---|---|
public | public | protected | private |
protected | protected | protected | private |
private | - | - | - |
Contents:
Ellipsis notation - Writing functions whose type and number of arguments are unknown.
Template - A high degree of generality, flexibility and efficiency.
Excel Add-In - Creating Add-Ins for Excel.
Database:
Ellipsis notation |
Writing functions whose type and number of arguments are unknown.
In C is possible to use functions whose type and number of arguments are unknown at the time that the function definition is compiled. An example is the printf() function, it has one required argument, namely the control string whose type is a pointer to char. Then there are zero or more additional arguments, working like an overload function. The definition of printf uses the ellipsis notation, as showed below
int printf ( const char * format, ... );
The theory behind
To write a function using ellipse notation is necessary to include the header file <stdarg.h>. It defines the macros necessary to work with the argument stack, they are:- va_dcl
- a macro that replaces the parameter declarations in the function definition.
- va_list
- a typedef that is used to declare a local state variable named ap, we use ap as an index to traverse the parameters.
- va_start
- a macro that initializes the state variable ap with the first argument in the list; we must call it before any invocations of va_arg or va_end. In ISO C, va_start has an additional parameter, the last fixed name, and sets the internal pointer in ap to point to the first variable argument passed to the function.
- va_arg
- a macro that returns the value of the next parameter in the parameter list and advances the internal argument pointer in ap to the next argument, if there is one. The type of the next argument, after the usual conversions, must be specified as type so that va_arg can compute its size on the stack. The first call to va_arg after calling va_start will return the value of the first parameter appearing in the variable portion of the parameter list.
- va_end
- implemented as either a function or macro, it should be called after all arguments have been read with va_arg. It does clean-up on ap and va_list; it resets the index of the list.
Some roules
- The functions should have at least one fixed argument. If this place-holder argument is not provided, there is no way to access other arguments.
- The last argument should be ellipsis (…) which means “and may be more arguments”.
- Before the ellipsis there is no need to have comma (,). In the Microsoft C++ specification the comma must exist. Hence according to Microsoft C++, int add( int x,…) is legal but int add( int x …) is not legal.
- Variable argument functions should have one terminating argument. You must decide how to build it, see the examples below.
Variable Promotions
- Type float is promoted to type double.
- Any signed or unsigned char, short, enumerated type, or bit field is converted to either a signed or an unsigned int using integral promotion.
- Any argument of class type is passed by value as a data structure; the copy is created by binary copying instead of by invoking the class’s copy constructor (if one exists).
So, if your argument types are of float type, you should expect the argument retrieved to be of type double and it is char or short, you should expect it to be signed or unsigned int.
This code will return wrong results.
float add(float x,...) { va_list list; va_start(list,x); float result=0; for(;;) { //I am passing float as expected type //in va_arg, but actually float has been //promoted to double. float p=va_arg(list,float); if(p==0) break; result+=p; } va_end(list); return result; }
Correct way, specify the type to be double.
float add(float x,...) { va_list list; va_start(list,x); float result=0; for(;;) { //Note: i am passing double as expected //datatype of argument, where actual //input was of type float. That is due to //variable promotion. float p=(float) va_arg(list,double); if(p==0) break; result+=p; } va_end(list); return result; }
Example
The sources below belongs to a unique code. It is presented here in pieces to be able include some comments. The examples uses the method in ISO C.
Include headers.
#include <iostream> // iostream.h: cout #include <stdarg.h> // stdarg.h: va_start, va_arg, va_list, va_end #include <cstdlib> // stdlib.h: EXIT_SUCCESS
The first function assumes that the last argument has a value that is uniquely different from the values in the rest of the list. It works with integers. 0 will stop the process, therefore is expected to be given by the last argument.
int Macro_Add (int operand, ...) { // comma is optional va_list operand_ptr; // pointer used to process the list of args int result = 0; if (operand != 0) { std::cout << "Macro_Add: " << operand << "\n"; result += operand; va_start(operand_ptr, operand); // init-z the list pointer while ( (operand=va_arg(operand_ptr, int)) != 0 ) { // extract next arg std::cout << "Macro_Add: " << operand << "\n"; result += operand; } va_end(operand_ptr); } return result; }
Here a NULL must be given to finish the argument list.
int add(int x, ...) { va_list operand_ptr; //initialize the va_list i.e int variable 'list' by the address //of first **unknown** variable argument by a call of va_start() macro va_start(operand_ptr,x); int result=x; for(;;) { // in loop, retreive each argument. Second argument to va_arg is // datatype of expected argument. int p=va_arg(operand_ptr,int); if(p==0) break; result+=p; } va_end(operand_ptr); // cleanup , set 'lsit' to NULL return result; }
Another way to process the list is to make the first argument a counter which indicates how many arguments follow. The function print_int() are build to work with integers and print_double() with doubles.
void print_int (int len, ...) { // comma is optional va_list operand_ptr; // pointer used to process the list of args int value; std::cout << "print_int: len= " << len << "\n"; if (len > 0) { va_start(operand_ptr, len); // init-z the list pointer for (int ndx=0; ndx < len; ndx++) { value=va_arg(operand_ptr, int); // extract next argument std::cout << "print_int: " << value << "\n"; // and advance one int } va_end(operand_ptr); } } void print_double (int len, ...) { va_list operand_ptr; double value; std::cout << "print_double: len= " << len << "\n"; if (len > 0) { va_start(operand_ptr, len); // init-z the list pointer for (int ndx=0; ndx < len; ndx++) { value=va_arg(operand_ptr, double); // extract next argument std::cout << "print_double: " << value << "\n";// and advance one double } va_end(operand_ptr); } }
print_args() has no specific type. The first integer argument defines the last argument in the list. Each new argument is preceded by an integer that specifies its type. In the argument list "0, 1, 8, 2, 8.8, 3, 'H', 0", the codes 1,2,3 mean integer, double, and char; zero says that there are no more arguments.
Attention: (Variable Promotions)
char is prompted to int when passed through ellipsis. Therefore the value is read as integer and than converted to char, char(va_arg(operand_ptr, int)).
void print_args (int lfp, ...) { // lfp, last fixed parameter va_list operand_ptr; // pointer used to process the list of args int i_val, type=-1; double d_val; char c_val; va_start(operand_ptr, lfp); // init-z the list pointer while (type != 0) { type=va_arg(operand_ptr, int); // extract next type code switch (type) { case 1 : i_val=va_arg(operand_ptr, int); // extract int argument std::cout << "i_val: " << i_val << "\n"; break; case 2 : d_val=va_arg(operand_ptr, double); // extract double arg std::cout << "d_val: " << d_val << "\n"; break; case 3 : c_val=char(va_arg(operand_ptr, int)); // extract char arg //char is prompted to int when passed through ellipsis. std::cout << "c_val: " << c_val << "\n"; break; }; } va_end(operand_ptr); }
Function Var_Param_List() operates similar to printf(). The first argument is a format string that specifies the type of the arguments in the argument list.
struct rational { int num, den; }; void Var_Param_List (const char* frmt, ...) { va_list p; va_start(p, frmt); for (; *frmt; frmt++) switch (*frmt) { case 'i': std::cout << "integer: " << va_arg(p, int) << std::endl; break; case 'd': std::cout << "double: " << va_arg(p, double) << std::endl; break; case 's': std::cout << "string: " << va_arg(p, char*) << std::endl; break; case 'c': std::cout << "char: " << char(va_arg(p, int)) << std::endl; break; case 'r': rational q; q = va_arg(p, rational); std::cout << "rational: " << q.num << "/" << q.den << std::endl; break; } va_end(p); }
The main() function shows function calls that exemplifies the use of all above functions.
int main () { std::cout << "*** MAIN START ***" << std::endl << std::endl; //last int is a 0 std::cout << "MAIN: Macro_Add: sum = " << Macro_Add(1,2,3,4,5,6,0) << "\n"; std::cout << "MAIN: Macro_Add: sum = " << add(1,2,3,4,5,6,NULL) << "\n"; //first int has the length print_int(3,9,8,7); //first int has the length print_double(6,9.9,8.8,7.7,6.6,5.5,4.4); // uses a dummy fixed parameter to identify the last argument int LastFixedParam = 0; print_args(LastFixedParam, 1,7,2,8.8,3,'H',3,'X',0); //first string specifies the elements type rational q = {4,5}; Var_Param_List("sicdrs", "Correia",33,'A',9.5,q,"last argument"); // Exit C++ program & return to operating system. std::cout << std::endl << "*** MAIN TERMINATION ***" << std::endl; return EXIT_SUCCESS; }
Template |
A high degree of generality, flexibility and efficiency.
template is a shema. A funciton or class declared as template will be instantiated according to the specification of its parameter types, i.e. an instantiated template is a specialization based on the defined parameter types.
Two tipical examples to understand template, a swap and a max function:
template <typename T> void swap ( T& x, T& y ){ T temp = x; x = y; y = temp; } template <class T> T max ( T x, T y ){ return (x>y)?x:y; } //instantiation int main(int, char**){ double x, y(2.5), z(6.6); x = max(y,z); return 0; }
Other template constructions and use:
Making use of default values
template <class T, T size> class C{ public: T array[size]; }; //instantiation int main(int, char**){ C<int, 5> z; C<char, 10> text; return 0; }
Multiple template
template <class T, class S> bool isGratherThen (T x, S y){ return (x>y); } //instantiation int main(int, char**){ double z(6.6); int c(6); if (isGratherThen(z, c)) //z>c else //c>z return 0; }
Instantiation in runtime is not possible
template <class T, class R, class S> S max (T x, R y){ return (x>y)?x:y; } //instantiation int main(int, char**){ double z, w, y(4.4); int a, b(3), c(6); z = max(y,c); //not possible a = max<int,int,int>(b,c); //explicit specialization, ok! return 0; }
Excel Add-In |
Creating Add-Ins for Excel.
Here a short source code example done with Visual Studio. Complete reference can be taken from MSDN, http://msdn.microsoft.com/en-us/library/aa730920.aspx and http://support.microsoft.com/kb/178474/ .
Microsoft excel developer's kit (Office Software Development Kit - SDK) is necessary. A free download can be made directly by Microsoft.
from excel:
Generic.c
Generic.h
Xlcall.h
XLCALL32.LIB
created files:
interp.h
interface.h
thermodynamik.h
interp2.c
File: interp.h
#include "generic.h" #define dimResult 200 // size of the permanent array for returning data to XL // Local function prototypes short ClipSize( XLOPER *multi ); // global function prototypes __declspec(dllexport) LPXLOPER Tc(void); // kritische Temperatur __declspec(dllexport) LPXLOPER TKtoC(double T); // Convert Temperature from K to gradC
File: Interp2.c
#include "interp.h" #include "intrface.h" HANDLE hArray; // temporary handle for returning large arrays to XL LPXLOPER Tc(void) // kritische Temperatur { double aux = 273.17; //null gradC static XLOPER tempXLOper; // Return Data tempXLOper.xltype = xltypeNum; tempXLOper.val.num = aux; return (LPXLOPER) &tempXLOper; } LPXLOPER TKtoC(double T) { double aux = 0; static XLOPER tempXLOper; // Return Data tempXLOper.xltype = xltypeNum; aux = T - 273.15; tempXLOper.val.num = aux; return (LPXLOPER) &tempXLOper; }
File: interface.h
#define kFunctionCount 43 #define kMaxFuncParms 11 const char *gModuleName = "\030RefrigerantR744 Add-In"; const int gFunctionCount = kFunctionCount, gMaxFuncParms = kMaxFuncParms; LPSTR functionParms[kFunctionCount][kMaxFuncParms] = { // function title, argument types, function name, arg names, type (1=func,2=cmd), // group name (func wizard), hotkey, help ID, func help string, (repeat) argument help strings {" Tc", " R", " Tc", " ", " 1", " RefrigerantR744 Add-In", " ", " refrigerant.hlp!300", " 'Critical Temperature' in [K]. " }, {" TKtoC", " RBB", " p", " T,rho", " 1", " RefrigerantR744 Add-In", " ", " refrigerant.hlp!300", " 'Pressure' [Pa] as a function of T and rho.", " 'Temperature' in [K] ", " 'Density' in [kg/m^3]. " }, }; LPSTR *gFuncParms = &functionParms[0][0];
Contents:
Missing Library - This application has failed to start because the application configuration is incorrect.
Database:
Missing Library |
This application has failed to start because the application configuration is incorrect.
Trying to distribute my application, that has been build with VC++ 9 Express Edition and Qt 4.5 in a WinXP with Service Pack 3, I got the following error.
Error: The Side-by-Side configuration information for "y:\MyQtApplication.exe" contains errors. This application has failed to start because the application configuration is incorrect.
German message:
The reason for this error are missing DLLs. To identify the missing libraries I have used the MS program (free for download) Dependency Walker. But it was not good enough. A better error message could be obtained with the MS application Event Viewer. It is present in a standard Windows installation.
Control Panel->Administrate Tools->Event Viewer->Windows Logs->Application
German version:
Systemsteuerung->Verwaltung->Ereignisanzeige->System
Here is possible to see a log with the error messages generated during application start. My application has shown some errors. Two of them have dependence with ‘Microsoft.VC90.DebugCRT’, another one my application itself. Other missing libraries are also reported and all related with the CRT .
The solution was to copy the missing CRT files including the manifest file.
The missing files were:
Msvcp90.dll, msvcm90.dll, msvcr90.dll, Microsoft.VC90.CRT.manifest
Msvcp90d.dll, msvcm90d.dll, msvcr90d.dll, Microsoft.VC90.DebugCRT.manifest
That's it!