Difference between revisions of "SDKCppLanguage"

From Apache OpenOffice Wiki
Jump to: navigation, search
m
m (To go further : the Enumeration Type Problem)
 
(20 intermediate revisions by 3 users not shown)
Line 1: Line 1:
{{Documentation/Banner}}
+
{{DocBanner}}
{{Documentation/NeedsRework}}
+
{{NeedsRework|EN}}
 
=The UNO C++ Language=
 
=The UNO C++ Language=
 
The aim of this chapter is to explain peculiarities of the C++ language in the UNO environment and not to provide skills on traditional C++. To put it differently, I want to give here the UNO/C++ background, quite helpful in getting us started.
 
The aim of this chapter is to explain peculiarities of the C++ language in the UNO environment and not to provide skills on traditional C++. To put it differently, I want to give here the UNO/C++ background, quite helpful in getting us started.
You can find e-Books on C++ [http://www.smart2help.com/e-books/ here].
+
You can find e-Books on C++ [https://bookauthority.org/books/best-c-plus-plus-ebooks here].
  
 
See also [[Uno/Article/Understanding_Uno|Understanding Uno]], [[Documentation/DevGuide/FirstSteps/Objects%2C_Interfaces%2C_and_Services|Objects, Interfaces, and Services]] and [[Documentation/BASIC_Guide/UNO|OOoBasic UNO Guide]] for a start with UNO.
 
See also [[Uno/Article/Understanding_Uno|Understanding Uno]], [[Documentation/DevGuide/FirstSteps/Objects%2C_Interfaces%2C_and_Services|Objects, Interfaces, and Services]] and [[Documentation/BASIC_Guide/UNO|OOoBasic UNO Guide]] for a start with UNO.
Line 9: Line 9:
 
== Our starting Example : Simple Binaries (Executable) ==
 
== Our starting Example : Simple Binaries (Executable) ==
  
We want now to start with a SDK example. The purpose of the  example presented is to create an executable which interacts with OpenOffice.org. We can imagine two kind of interactions : direct interaction with OpenOffice.org or interaction with one of OOo's shared library. We focus on this second case where the makefile is simpler. The shared library involved is then cppuhelper.uno.so (cppuhelper.uno.dll under Windows). Former case will be examined later.
+
We want now to start with a SDK example. The purpose of the  example presented is to create an executable which interacts with {{AOo}}. We can imagine two kind of interactions : direct interaction with OpenOffice or interaction with one of AOO's shared library. We focus on this second case where the makefile is simpler. The shared library involved is then cppuhelper.uno.so (cppuhelper.uno.dll under Windows). Former case will be examined later.
I assume (I know nobody of the SDK team) this example is given to provide the simplest example we can do with the SDK. This is the Lifetime example: see at “<OpenOffice.org1.1_SDK>/examples/DevelopersGuide/ProfUNO/Lifetime”
+
I assume (I know nobody of the SDK team) this example is given to provide the simplest example we can do with the SDK. This is the Lifetime example: see at “<SDK_Folder>/examples/DevelopersGuide/ProfUNO/Lifetime”
  
 
Before diving into the examples, you will need to set up your programming environment so you can create UNO programs. What's required depends on what platform you're working. This is shown in the first example with LINUX platform.
 
Before diving into the examples, you will need to set up your programming environment so you can create UNO programs. What's required depends on what platform you're working. This is shown in the first example with LINUX platform.
 
To check this example you only have to launch the makefile :
 
To check this example you only have to launch the makefile :
{{Documentation/Linux|
+
{{Lin|
 
<pre>
 
<pre>
cd <OpenOffice.org1.1_SDK>
+
cd <SDK_Folder>
 
./setsdkenv_unix
 
./setsdkenv_unix
 
cd examples/DevelopersGuide/ProfUNO/Lifetime
 
cd examples/DevelopersGuide/ProfUNO/Lifetime
Line 23: Line 23:
 
</pre>
 
</pre>
 
}}
 
}}
The last command line only launch the binary executable “ProfUnoLifetime” which interact with cpphelper.uno.so (cppuhelper.uno.dll under Windows) even if OpenOffice.org is not running.
+
The last command line only launch the binary executable “ProfUnoLifetime” which interact with cpphelper.uno.so (cppuhelper.uno.dll under Windows) even if {{AOo}} is not running.
 
This example creates and releases an object, nothing more. The constructor and destructor of the object only write out a message. Its little size allows us to give its code here:
 
This example creates and releases an object, nothing more. The constructor and destructor of the object only write out a message. Its little size allows us to give its code here:
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
// Listing 1 First Example (from SDK)
 
// Listing 1 First Example (from SDK)
 
// C++
 
// C++
Line 33: Line 33:
 
class MyOWeakObject : public ::cppu::OWeakObject
 
class MyOWeakObject : public ::cppu::OWeakObject
 
{
 
{
public:
+
public:  
    MyOWeakObject() { printf( "constructed\n" ); }
+
MyOWeakObject()  
    ~MyOWeakObject() { printf( "destructed\n" ); }
+
{  
 +
fprintf( stdout, "constructed\n" );  
 +
}  
 +
~MyOWeakObject()  
 +
{  
 +
fprintf( stdout, "destructed\n" );  
 +
}
 
};
 
};
 
  
 
void simple_object_creation_and_destruction()
 
void simple_object_creation_and_destruction()
{
+
{  
    // create the UNO object
+
// create the UNO object  
    com::sun::star::uno::XInterface * p = new MyOWeakObject();
+
com::sun::star::uno::XInterface * p = new MyOWeakObject();  
 
+
 
    // acquire it, refcount becomes one
+
// acquire it, refcount becomes one  
    p->acquire();
+
p->acquire();  
 
+
fprintf( stdout, "before release\n" );  
    printf( "before release\n" );
+
 
 
+
// release it, refcount drops to zero  
    // release it, refcount drops to zero
+
p->release();  
    p->release();
+
fprintf( stdout, "after release\n" );
 
+
    printf( "after release\n" );
+
 
}
 
}
 
 
 
int main( char * argv[] )
 
int main( char * argv[] )
{
+
{  
    simple_object_creation_and_destruction();
+
simple_object_creation_and_destruction();  
    return 0;
+
return 0;
 
}
 
}
</source>
+
</syntaxhighlight>
  
The two methods acquire and release will be encountered later. What exactly they do is not important for the moment. This example shows us how to write a class which inherits from an other class, how to write and call methods and how to instantiate the class.
+
The two methods acquire and release will be encountered later. What exactly they do is not important for the moment. This example shows us how to write a class which inherits from another class, how to write and call methods and how to instantiate the class.
All the listings given below only need to modify this C++ code compile it and run it. You can therefore use the same makefile by possibly changing the name of the source file  (tackled in next section).
+
All the listings given below only need to modify this C++ code, compile it and run it. You can therefore use the same makefile by possibly changing the name of the source file  (tackled in next section).
  
 
== Types ==
 
== Types ==
Line 99: Line 100:
 
example. Replace object_lifetime.cxx completely with the listing below (don't forget to save the old file)
 
example. Replace object_lifetime.cxx completely with the listing below (don't forget to save the old file)
  
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
// Listing 2 A short UNO Program  
 
// Listing 2 A short UNO Program  
 
// C++
 
// C++
Line 111: Line 112:
 
   return 0;
 
   return 0;
 
}
 
}
</source>
+
</syntaxhighlight>
  
 
then launch  
 
then launch  
Line 124: Line 125:
 
A sequence is an abstract view of a set of UNO types with a variable number of elements. As first example, we give a very simple program:
 
A sequence is an abstract view of a set of UNO types with a variable number of elements. As first example, we give a very simple program:
  
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
// Listing 3  UNO Sequences
 
// Listing 3  UNO Sequences
 
// C++
 
// C++
Line 139: Line 140:
 
     return 0;
 
     return 0;
 
}
 
}
</source>
+
</syntaxhighlight>
  
 
The important things to notice are as follows:
 
The important things to notice are as follows:
 
* the type of each element of the set is put between angular brackets: "<" and ">". In the example above sal_int32 is the type.
 
* the type of each element of the set is put between angular brackets: "<" and ">". In the example above sal_int32 is the type.
 
* declaration of sequence is done with parentheses "(" and ")" and the number of elements of the sequence between them.  In the example above a sequence of five sal_Int32 elements is declared.
 
* declaration of sequence is done with parentheses "(" and ")" and the number of elements of the sequence between them.  In the example above a sequence of five sal_Int32 elements is declared.
* accessing elements of the sequence is done with "[" and "]" and an index between them (generaly called subscript operator). This allows us to say that sequences are referenced like arrays. But they are different in some way, for instance they don't have a fixed size.  
+
* accessing elements of the sequence is done with "[" and "]" and an index between them (generally called subscript operator). This allows us to say that sequences are referenced like arrays. But they are different in some way, for instance they don't have a fixed size.  
* We have to include Sequence.hxx file in a program when using Sequence. Note that this file is provided with the SDK and this not always the case for all hxx files (some of them have to be reconstructed).
+
* We have to include Sequence.hxx file in a program when using Sequence. Note that this file is provided with the SDK and this is not always the case for all hxx files (some of them have to be reconstructed).
We have to use the correct namespace with adding "using namespace ..." If you don't use this statement you have to write com::sun::star::uno::Sequence instead of Sequence.
+
We have to use the correct namespace with adding "using namespace " If you don't use this statement, you have to write com::sun::star::uno::Sequence instead of Sequence.
 
A Sequence can be created with arbitrary UNO type but not with other types.  
 
A Sequence can be created with arbitrary UNO type but not with other types.  
 
The object SetOfInt has many methods. We give an example to show some of them:
 
The object SetOfInt has many methods. We give an example to show some of them:
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
// Listing 4 Examples of using Sequence Methods
 
// Listing 4 Examples of using Sequence Methods
 
// C++
 
// C++
Line 173: Line 174:
 
return 0;
 
return 0;
 
}
 
}
</source>
+
</syntaxhighlight>
  
 
The comments explain what is printed out when executing this example. The method realloc is particularly important: it allows the size of set to change.
 
The comments explain what is printed out when executing this example. The method realloc is particularly important: it allows the size of set to change.
Line 179: Line 180:
 
Let us focus on using sequences in function or as parameter. An example is again more descriptive than a long text:
 
Let us focus on using sequences in function or as parameter. An example is again more descriptive than a long text:
  
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
// Listing 5 Sequence and Parameters  
 
// Listing 5 Sequence and Parameters  
 
// C++
 
// C++
Line 194: Line 195:
 
SeqOfInt=SeqOfInt2;
 
SeqOfInt=SeqOfInt2;
 
}
 
}
</source>
+
</syntaxhighlight>
 
An obvious call could be :
 
An obvious call could be :
  
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
// Listing 6 Sequence and Parameters (following)  
 
// Listing 6 Sequence and Parameters (following)  
 
// C++
 
// C++
Line 204: Line 205:
 
initSequence2(SetOfInt);
 
initSequence2(SetOfInt);
 
printf("New length : %d\n",SetOfInt.getLength()); // prints out 4
 
printf("New length : %d\n",SetOfInt.getLength()); // prints out 4
</source>
+
</syntaxhighlight>
 
We cannot leave this section without adding that operators == and != are available with sequences. Note also that "toUnoSequence()", "getCppuSequenceType()" and "getCharSequenceCppuType()" are also member functions.
 
We cannot leave this section without adding that operators == and != are available with sequences. Note also that "toUnoSequence()", "getCppuSequenceType()" and "getCharSequenceCppuType()" are also member functions.
  
 
Passing a sequence into a function by value is, like a vector, somewhat inefficient because the function must make a copy of all elements. It's better to use a constant reference as shown below:
 
Passing a sequence into a function by value is, like a vector, somewhat inefficient because the function must make a copy of all elements. It's better to use a constant reference as shown below:
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
// Listing 7 The Constant Reference method
 
// Listing 7 The Constant Reference method
 
//C++
 
//C++
Line 236: Line 237:
 
     return 0;
 
     return 0;
 
}
 
}
</source>
+
</syntaxhighlight>
  
 
See other material in Developer's Guide (UNO C++ Binding).
 
See other material in Developer's Guide (UNO C++ Binding).
Line 261: Line 262:
 
If OUStr is a OUString object, we give this example for conversion:
 
If OUStr is a OUString object, we give this example for conversion:
  
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
// Listing 8 Converting OUString into OString
 
// Listing 8 Converting OUString into OString
 
// C++
 
// C++
Line 268: Line 269:
 
OString o = OUStringToOString( OUStr, RTL_TEXTENCODING_ASCII_US );
 
OString o = OUStringToOString( OUStr, RTL_TEXTENCODING_ASCII_US );
 
printf( "Conversion result : %s\n", o.pData->buffer );
 
printf( "Conversion result : %s\n", o.pData->buffer );
</source>
+
</syntaxhighlight>
  
 
==== OString to OUString ====
 
==== OString to OUString ====
 
The inverse conversion is easy too :
 
The inverse conversion is easy too :
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
// Listing 9 Converting OString into OUString
 
// Listing 9 Converting OString into OUString
 
// C++
 
// C++
 
OUString foo;
 
OUString foo;
foo = OUString::createFromAscii("Hi every body");
+
foo = OUString::createFromAscii("Hi everybody");
</source>
+
</syntaxhighlight>
  
 
Here is a complete conversion example:
 
Here is a complete conversion example:
  
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
// Listing 10 A complete Example
 
// Listing 10 A complete Example
 
// C++
 
// C++
Line 291: Line 292:
 
main( ) {
 
main( ) {
 
OUString OUStr;
 
OUString OUStr;
OUStr = OUString::createFromAscii("Hi every body");
+
OUStr = OUString::createFromAscii("Hi everybody");
 
OString OStr = OUStringToOString( OUStr, RTL_TEXTENCODING_ASCII_US );
 
OString OStr = OUStringToOString( OUStr, RTL_TEXTENCODING_ASCII_US );
 
printf( "OUStr was : %s\n", OStr.pData->buffer );
 
printf( "OUStr was : %s\n", OStr.pData->buffer );
 
return 0;
 
return 0;
 
}
 
}
</source>
+
</syntaxhighlight>
  
 
We see that a rtl namespace has to be used. If not, please replace OUString by ::rtl::OUString.
 
We see that a rtl namespace has to be used. If not, please replace OUString by ::rtl::OUString.
Line 309: Line 310:
 
can be used to compare both strings. A function like compareTo(), which is part of the O(U)String-class is called a member function. The O(U)String class offers a large number of these member functions, as well as extensions of some well-known operators, like the assignment (=) and the comparison operator (==). These operators and functions are discussed in the following sections.
 
can be used to compare both strings. A function like compareTo(), which is part of the O(U)String-class is called a member function. The O(U)String class offers a large number of these member functions, as well as extensions of some well-known operators, like the assignment (=) and the comparison operator (==). These operators and functions are discussed in the following sections.
 
The OUString and OString methods are similar: we give a complete example which shows some of them:
 
The OUString and OString methods are similar: we give a complete example which shows some of them:
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
// Listing 11 A more complete Example
 
// Listing 11 A more complete Example
 
// C++
 
// C++
Line 323: Line 324:
 
OStr1="Hi every body";
 
OStr1="Hi every body";
 
OStr2="every body";
 
OStr2="every body";
OUStr1 = OUString::createFromAscii("Hi every body");
+
OUStr1 = OUString::createFromAscii("Hi everybody");
OUStr2 = OUString::createFromAscii("Hi every body");
+
OUStr2 = OUString::createFromAscii("Hi everybody");
 
// Returns the length of this string
 
// Returns the length of this string
 
printf("Length : %d\n",OUStr1.getLength()); // prints out 13
 
printf("Length : %d\n",OUStr1.getLength()); // prints out 13
Line 339: Line 340:
 
// Perform a comparison of a substring in this string
 
// Perform a comparison of a substring in this string
 
// is "every body" in position 3 of OUStr1 ?
 
// is "every body" in position 3 of OUStr1 ?
if (OUStr1.match(OUString::createFromAscii("every body"),3))
+
if (OUStr1.match(OUString::createFromAscii("everybody"),3))
 
printf("match : OK\n"); //prints out match : OK
 
printf("match : OK\n"); //prints out match : OK
 
// Perform a comparison of a substring in this string
 
// Perform a comparison of a substring in this string
Line 357: Line 358:
 
return 0;
 
return 0;
 
}
 
}
</source>
+
</syntaxhighlight>
We can also see in this program how the concat method (three last lines) is used. The toFloat() conversion method is not alone: toBoolean(), toChar(), toInt32(), toInt64() , toDouble(), toAsciiLowerCase() and toAsciiUpperCase() exist also. Now we terminate with presenting some other methods (see C++ material):
+
We can also see in this program how the concat method (three last lines) is used. The toFloat() conversion method is not alone: toBoolean(), toChar(), toInt32(), toInt64(), toDouble(), toAsciiLowerCase() and toAsciiUpperCase() exist also. Now we terminate with presenting some other methods (see C++ material):
  
 
; String methods
 
; String methods
Line 386: Line 387:
 
|}
 
|}
  
I cannot close this section without giving a code found in OOo source /OOB680_m5/registry/source/regimpl.cxx
+
I cannot close this section without giving a code found in AOo source /OOB680_m5/registry/source/regimpl.cxx
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
//Listing 11-b Printing out an OUString
 
//Listing 11-b Printing out an OUString
 
// C++
 
// C++
Line 404: Line 405:
 
     printf("\"");
 
     printf("\"");
 
}
 
}
</source>
+
</syntaxhighlight>
If you want to see the content of an OUString with standard output, you have only to convert it in OString :
+
If you want to see the content of an OUString with standard output, you have only to convert it to OString :
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
//Listing 11-c Printing out an OUString with standard C++ output
 
//Listing 11-c Printing out an OUString with standard C++ output
 
// C++
 
// C++
Line 412: Line 413:
 
   OString  OStr  = OUStringToOString ( OUStr,RTL_TEXTENCODING_UTF8);
 
   OString  OStr  = OUStringToOString ( OUStr,RTL_TEXTENCODING_UTF8);
 
   cout <<  Ostr << endl;
 
   cout <<  Ostr << endl;
</source>
+
</syntaxhighlight>
  
 
===File Path ===
 
===File Path ===
  
{{Documentation/Linux|Linux related content : the file paths are OS-dependent. To remove this dependency, UNO use URL and a way to transform a file path to an URL. We show an example now
+
{{Lin|Linux related content : the file paths are OS-dependent. To remove this dependency, UNO use URL and a way to transform a file path to an URL. We show an example now
  
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
// Listing 12 UNO URL
 
// Listing 12 UNO URL
 
// C++
 
// C++
Line 429: Line 430:
 
//   OUString::createFromAscii("\"C:\\My Documents\\tata.sxc\""),sDocUrl);
 
//   OUString::createFromAscii("\"C:\\My Documents\\tata.sxc\""),sDocUrl);
  
</source>
+
</syntaxhighlight>
  
 
A complete example is given in the below listing :
 
A complete example is given in the below listing :
  
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
// Listing 13 Using URL
 
// Listing 13 Using URL
 
// C++
 
// C++
Line 453: Line 454:
 
return 0;
 
return 0;
 
}
 
}
</source>
+
</syntaxhighlight>
  
 
which shows how to use the conversion. Remember that we work with UNO and therefore the URL is an OUString.
 
which shows how to use the conversion. Remember that we work with UNO and therefore the URL is an OUString.
 
}}
 
}}
  
{{Documentation/Windows|Only file paths have to be changed to transform these programs into Windows programs}}
+
{{Win|Only file paths have to be changed to transform these programs into Windows programs}}
  
 
=== SDK Example ===
 
=== SDK Example ===
 
Here is some code provided by SDK :
 
Here is some code provided by SDK :
  
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
// Listing 14 SDK Example
 
// Listing 14 SDK Example
 
// C++
 
// C++
Line 511: Line 512:
 
     return 0;
 
     return 0;
 
}
 
}
</source>
+
</syntaxhighlight>
 
This example shows an other way to use OUString, OString and buffer.
 
This example shows an other way to use OUString, OString and buffer.
 
   
 
   
 
For performance analysis see  
 
For performance analysis see  
[http://udk.openoffice.org/common/man/concept/string_invest.html Some String Performance Thoughts]
+
[https://wiki.openoffice.org/wiki/Uno/Binary/Analysis/String_Performance Some String Performance Thoughts]
  
 
===Sequence of Strings===
 
===Sequence of Strings===
 
Sequence has been tackled in a previous [[SDKCppLanguage#Sequences|section]]. If you want to construct a Sequence of string (useful in list box ...) have a look on this piece of code :
 
Sequence has been tackled in a previous [[SDKCppLanguage#Sequences|section]]. If you want to construct a Sequence of string (useful in list box ...) have a look on this piece of code :
  
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
// Listing 15 An Example of Sequence of Strings
 
// Listing 15 An Example of Sequence of Strings
 
// C++
 
// C++
Line 536: Line 537:
 
printf("-- %s\n",toPrintOut.pData->buffer);
 
printf("-- %s\n",toPrintOut.pData->buffer);
 
}
 
}
</source>
+
</syntaxhighlight>
 
This code prints out in the shell console :
 
This code prints out in the shell console :
 
<pre>
 
<pre>
Line 546: Line 547:
 
It is easy to understand and therefore I have nothing more to say about it.
 
It is easy to understand and therefore I have nothing more to say about it.
  
===Exercise on Sequence of Strings===
+
===Exercise on Sequence of Strings===
 
Write and test the following "convert2SeqOUStrInDEBUGMODE" function with a sequence of "sal_Int8" as parameter and which returns a sequence of Strings in a format like the dump method of the old "debug" of DOS. This format  [[UNO_registery_and_Bootstrapping#C.2B.2B_Code_to_recover_Information_in_a_Binary_Sequence|will be used here]], but without this function.
 
Write and test the following "convert2SeqOUStrInDEBUGMODE" function with a sequence of "sal_Int8" as parameter and which returns a sequence of Strings in a format like the dump method of the old "debug" of DOS. This format  [[UNO_registery_and_Bootstrapping#C.2B.2B_Code_to_recover_Information_in_a_Binary_Sequence|will be used here]], but without this function.
  
 
'''Solution''' : here is the corresponng function code
 
'''Solution''' : here is the corresponng function code
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
Sequence< OUString > convert2SeqOUStrInDEBUGMODE(Sequence < sal_Int8 > seqBytes){
 
Sequence< OUString > convert2SeqOUStrInDEBUGMODE(Sequence < sal_Int8 > seqBytes){
 
   sal_Int8 Hexa[16]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
 
   sal_Int8 Hexa[16]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
Line 601: Line 602:
 
   return SeqOUStr;
 
   return SeqOUStr;
 
}
 
}
</source>
+
</syntaxhighlight>
 
and now how this function can be used :
 
and now how this function can be used :
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
sal_Int8 sourceArray[32]={1,22,23,24,55,56,57,8,9,10,11,12,13,14,15,16,17,18,19,61,62,-32,-33,-34,-35,26,127,-31,29,56,23,67};
 
sal_Int8 sourceArray[32]={1,22,23,24,55,56,57,8,9,10,11,12,13,14,15,16,17,18,19,61,62,-32,-33,-34,-35,26,127,-31,29,56,23,67};
 
         Sequence < sal_Int8 > seqBytes(sourceArray,32);
 
         Sequence < sal_Int8 > seqBytes(sourceArray,32);
Line 610: Line 611:
 
printf("%s\n",OUStringToOString( seqOUStr[1], RTL_TEXTENCODING_ASCII_US ).pData->buffer);
 
printf("%s\n",OUStringToOString( seqOUStr[1], RTL_TEXTENCODING_ASCII_US ).pData->buffer);
 
printf("%s\n",OUStringToOString( seqOUStr[2], RTL_TEXTENCODING_ASCII_US ).pData->buffer);
 
printf("%s\n",OUStringToOString( seqOUStr[2], RTL_TEXTENCODING_ASCII_US ).pData->buffer);
</source>  
+
</syntaxhighlight>  
 
In our [[Constructing_Helpers#Reflection_Helper|introspection tool]] we need also this format but in one string. It's easy to write the corresponding code :
 
In our [[Constructing_Helpers#Reflection_Helper|introspection tool]] we need also this format but in one string. It's easy to write the corresponding code :
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
OUString convert2OUStrInDEBUGMODE(Sequence < sal_Int8 > seqBytes){
 
OUString convert2OUStrInDEBUGMODE(Sequence < sal_Int8 > seqBytes){
 
   Sequence <OUString> SeqOUStr = convert2SeqOUStrInDEBUGMODE(seqBytes);
 
   Sequence <OUString> SeqOUStr = convert2SeqOUStrInDEBUGMODE(seqBytes);
Line 620: Line 621:
 
   return OUStr;
 
   return OUStr;
 
}
 
}
</source>
+
</syntaxhighlight>
 
which can be used with :
 
which can be used with :
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
sal_Int8 sourceArray[32]={1,22,23,24,55,56,57,8,9,10,11,12,13,14,15,16,17,18,19,61,62,-32,-33,-34,-35,26,127,-31,29,56,23,67};
 
sal_Int8 sourceArray[32]={1,22,23,24,55,56,57,8,9,10,11,12,13,14,15,16,17,18,19,61,62,-32,-33,-34,-35,26,127,-31,29,56,23,67};
 
         Sequence < sal_Int8 > seqBytes(sourceArray,32);
 
         Sequence < sal_Int8 > seqBytes(sourceArray,32);
Line 628: Line 629:
 
         OUString OUStr=convert2OUStrInDEBUGMODE(seqBytes);
 
         OUString OUStr=convert2OUStrInDEBUGMODE(seqBytes);
 
         printf("%s\n",OUStringToOString( OUStr, RTL_TEXTENCODING_ASCII_US ).pData->buffer);
 
         printf("%s\n",OUStringToOString( OUStr, RTL_TEXTENCODING_ASCII_US ).pData->buffer);
</source>
+
</syntaxhighlight>
  
 
== [[Uno/Cpp/Tutorials/Introduction_to_Cpp_Uno#Any|Any]] ==
 
== [[Uno/Cpp/Tutorials/Introduction_to_Cpp_Uno#Any|Any]] ==
 
We can find also good materials in Developer's guide on [[Documentation/DevGuide/FirstSteps/Any|Any type]]. [[Uno/Cpp/Tutorials/Introduction_to_Cpp_Uno#Any|Any]] is easy to use only with <<= and >>= operators and we then often use intermediate variables. We can use also the build-in “makeAny” function :
 
We can find also good materials in Developer's guide on [[Documentation/DevGuide/FirstSteps/Any|Any type]]. [[Uno/Cpp/Tutorials/Introduction_to_Cpp_Uno#Any|Any]] is easy to use only with <<= and >>= operators and we then often use intermediate variables. We can use also the build-in “makeAny” function :
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
// Listing 16 makeAny Example
 
// Listing 16 makeAny Example
 
// C++
 
// C++
 
Any any = makeAny((long) 1000);
 
Any any = makeAny((long) 1000);
</source>
+
</syntaxhighlight>
  
 
We give first an example above :
 
We give first an example above :
  
<source lang="cpp">]
+
<syntaxhighlight lang="cpp">
 
//Listing 17 Any Example
 
//Listing 17 Any Example
 
// C++
 
// C++
Line 682: Line 683:
 
return 0;
 
return 0;
 
}
 
}
</source>
+
</syntaxhighlight>
  
 
This program prints out :
 
This program prints out :
Line 693: Line 694:
 
Another important problem is a sequence of sequence of Any : we give now a piece of code without explanation :
 
Another important problem is a sequence of sequence of Any : we give now a piece of code without explanation :
  
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
// Listing 18 Sequence of Sequence of Any
 
// Listing 18 Sequence of Sequence of Any
 
// C++
 
// C++
Line 702: Line 703:
 
aValues2[0] <<=  (double)2.2; aValues2[1] <<= OUString::createFromAscii("Hi");
 
aValues2[0] <<=  (double)2.2; aValues2[1] <<= OUString::createFromAscii("Hi");
 
aValues[1] = aValues2;
 
aValues[1] = aValues2;
</source>
+
</syntaxhighlight>
 
This code uses two sequences. I have not found an other simpler way to do that. If anybody has a more straightforward solution, I would be happy learn about it.  
 
This code uses two sequences. I have not found an other simpler way to do that. If anybody has a more straightforward solution, I would be happy learn about it.  
 
If it is possible to access directely a value in a 2D array but I found only one means using an intermediate sequence (avalues2) in the case of sequence of sequence.
 
If it is possible to access directely a value in a 2D array but I found only one means using an intermediate sequence (avalues2) in the case of sequence of sequence.
Line 708: Line 709:
 
== Files ==
 
== Files ==
  
{{Documentation/Linux|
+
{{Lin|
 
+
We now want to create a textfile named "demo.txt". Here is the code to do this :
We want now create a text file named "demo.txt". Here is the code to do this :
+
  
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
// Listing 19 A little Example manipulating Files
 
// Listing 19 A little Example manipulating Files
 
// C++
 
// C++
Line 736: Line 736:
 
return 0;
 
return 0;
 
}
 
}
</source>
+
</syntaxhighlight>
 
}}
 
}}
{{Documentation/Note|The method open is not described in C++ documentation !!! I have found it while reading the “file.hxx” header file.}}  
+
{{Note|The method '''open''' is not described in C++ documentation !!! I have found it while reading the “file.hxx” header file.}}  
  
 
The flag you can pass to the "open" method are :  OpenFlag_Write,  OpenFlag_Read,  OpenFlag_Create. The " using namespace osl;" is obligatory even if the compiler doesn't complain without.
 
The flag you can pass to the "open" method are :  OpenFlag_Write,  OpenFlag_Read,  OpenFlag_Create. The " using namespace osl;" is obligatory even if the compiler doesn't complain without.
 
When a file is open, you can use the  methods above :  
 
When a file is open, you can use the  methods above :  
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
// C++
 
// C++
 
// Write a number of bytes to a file
 
// Write a number of bytes to a file
Line 761: Line 761:
 
// Set the internal position pointer of an open file.  
 
// Set the internal position pointer of an open file.  
 
setPos( sal_uInt32 uHow, sal_Int64 uPos );
 
setPos( sal_uInt32 uHow, sal_Int64 uPos );
</source>
+
</syntaxhighlight>
 
There are other possibilities : move, remove, copy... See the documentation or read the file.hxx file.
 
There are other possibilities : move, remove, copy... See the documentation or read the file.hxx file.
  
See [http://udk.openoffice.org/common/man/concept/streams.html « Streaming interfaces »]
+
See [https://www.openoffice.org/udk/common/man/concept/streams.html « Streaming interfaces »]
 
for an other way to use files.
 
for an other way to use files.
  
Line 770: Line 770:
  
 
It would be great to use the Thread Class but it's  so badly documented that we begin with process instead thread.
 
It would be great to use the Thread Class but it's  so badly documented that we begin with process instead thread.
Starting from an example posted in the forum Working with a Spreadsheet Document in C++ (by lirincy). This example gives a working code to start OOo if not started when launching a binary executable. We remove what was not usefull for us and give two examples.
+
Starting from an example posted in the forum Working with a Spreadsheet Document in C++ (by lirincy). This example gives a working code to start AOO if not started when launching a binary executable. We remove what was not usefull for us and give two examples.
{{Documentation/Linux|
+
{{Lin|
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
// Listing 20 A Process Example
 
// Listing 20 A Process Example
 
// C++
 
// C++
Line 805: Line 805:
 
return 0;
 
return 0;
 
}
 
}
</source>
+
</syntaxhighlight>
 
}}
 
}}
{{Documentation/Note|Note that the demo file is an existing binary in /home/smoutou.}}
+
{{Note|Note that the demo file is an existing binary in /home/smoutou.}}
 
If you want to pass something to the launched program see AppArgs variable in the second example :
 
If you want to pass something to the launched program see AppArgs variable in the second example :
{{Documentation/Linux|
+
{{Lin|
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
// Listing 21 A second Process Example
 
// Listing 21 A second Process Example
 
// C++
 
// C++
Line 845: Line 845:
 
return 0;
 
return 0;
 
}
 
}
</source>
+
</syntaxhighlight>
 
}}
 
}}
 
I have tried working with thread but only with C style at the moment (not with using the thread class). Here is my first example code :
 
I have tried working with thread but only with C style at the moment (not with using the thread class). Here is my first example code :
{{Documentation/Linux|
+
{{Lin|
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
// Listing 22 A working Thread Example
 
// Listing 22 A working Thread Example
 
// C++
 
// C++
Line 899: Line 899:
 
return 0;
 
return 0;
 
}
 
}
</source>
+
</syntaxhighlight>
 
}}
 
}}
What is printed out is depending on how screen is managed by your OS. Under Linux I obtained something like :
+
What is printed out is depending on how the screen is managed by your OS. Under Linux I obtained something like this :
 
<pre>
 
<pre>
 
  ...
 
  ...
Line 915: Line 915:
 
  ....
 
  ....
 
</pre>
 
</pre>
Here you can see the second thread launched writes at first and only when the main sleeping is terminated thread two is writing out. The other thread primitives can be found in osl/thread.h :
+
Here you can see the second thread launched writes at first and only when the main sleeping is terminated, thread two is writing out. The other thread primitives can be found in osl/thread.h :
 
<pre>
 
<pre>
 
/** Create the thread, using the function-ptr pWorker as
 
/** Create the thread, using the function-ptr pWorker as
Line 971: Line 971:
  
 
== To go further : the Enumeration Type Problem ==
 
== To go further : the Enumeration Type Problem ==
Sometimes we will encounter enumeration values. We have to learn how to resolve the problem. An example will be discussed later but we give it without its context here. The Cell content in OOoCalc is described by an enumeration. How can I know that, is not easy with the previous material, but I want to tackle the problem even if too soon to understand for a first reading.
+
Sometimes we will encounter enumeration values. We have to learn how to resolve the problem. An example will be discussed later but we give it without its context here. The Cell content in {{AOo}} Calc is described by an enumeration. How can I know that, is not easy with the previous material, but I want to tackle the problem even if too soon to understand for a first reading.
  
 
All types used in programming are described in IDL files. Sometimes these IDL files are used to create hpp/hxx files.
 
All types used in programming are described in IDL files. Sometimes these IDL files are used to create hpp/hxx files.
Line 977: Line 977:
 
This example is around CellContentType.idl file. Here is the summary of this file where we remove comments :
 
This example is around CellContentType.idl file. Here is the summary of this file where we remove comments :
  
<source lang="idl">
+
<syntaxhighlight lang="idl">
 
// Listing 23  CellContentType Enumeration type (IDL File)
 
// Listing 23  CellContentType Enumeration type (IDL File)
 
// IDL
 
// IDL
Line 996: Line 996:
 
} // sun
 
} // sun
 
} // com
 
} // com
</source>
+
</syntaxhighlight>
 
Three tips can be used when using this kind of enumeration :
 
Three tips can be used when using this kind of enumeration :
 
* In C++ a corresponding using namespace is necessary
 
* In C++ a corresponding using namespace is necessary
Line 1,002: Line 1,002:
 
This line can be drawn from the IDL file.
 
This line can be drawn from the IDL file.
 
* In C++ an include directive is necessary
 
* In C++ an include directive is necessary
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
#include <com/sun/star/table/CellContentType.hpp>
 
#include <com/sun/star/table/CellContentType.hpp>
</source>
+
</syntaxhighlight>
 
The  name of the file to include and the path is easy to draw from IDL file.
 
The  name of the file to include and the path is easy to draw from IDL file.
 
* We have to construct the previous hpp file. This is done with adding the red line above in the makefile :
 
* We have to construct the previous hpp file. This is done with adding the red line above in the makefile :
Line 1,026: Line 1,026:
 
</pre>
 
</pre>
 
After you can use this enumeration without problem like this :
 
After you can use this enumeration without problem like this :
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
// Listing 24 Enumeration type : an Example
 
// Listing 24 Enumeration type : an Example
 
//C++
 
//C++
Line 1,042: Line 1,042:
 
case CellContentType_FORMULA : printf("Formula\n");break;
 
case CellContentType_FORMULA : printf("Formula\n");break;
 
}
 
}
</source>
+
</syntaxhighlight>
 
What is shown here is a general SDK's feature : we construct a hpp file starting from an IDL file. This is so important and unexpected for beginners that I will repeat many times these explanations [[UNO_automation_with_a_binary_%28executable%29#Introduction_to_Bootstrapping|later]] and more deeply [[IDL_Files_and_Cpp#Getting_an_interface_in_C.2B.2B|here]].
 
What is shown here is a general SDK's feature : we construct a hpp file starting from an IDL file. This is so important and unexpected for beginners that I will repeat many times these explanations [[UNO_automation_with_a_binary_%28executable%29#Introduction_to_Bootstrapping|later]] and more deeply [[IDL_Files_and_Cpp#Getting_an_interface_in_C.2B.2B|here]].
  
Line 1,048: Line 1,048:
 
Values are not always defined with enumeration types as shown in previous section. Sometimes constants are used when programming with UNO. One example is again tackled [[OpenOffice_Calc#The_Compute_Function__Example|later]] but we want again writes on it now. We first present the corresponding IDL file (as an example)
 
Values are not always defined with enumeration types as shown in previous section. Sometimes constants are used when programming with UNO. One example is again tackled [[OpenOffice_Calc#The_Compute_Function__Example|later]] but we want again writes on it now. We first present the corresponding IDL file (as an example)
  
<source lang="idl">
+
<syntaxhighlight lang="idl">
 
// Listing 25 CellFlags Constants type : IDL File  
 
// Listing 25 CellFlags Constants type : IDL File  
 
//IDL
 
//IDL
Line 1,065: Line 1,065:
 
};
 
};
 
}; }; }; };
 
}; }; }; };
</source>
+
</syntaxhighlight>
 
Compare this listing with Listing 23 to see the differences.
 
Compare this listing with Listing 23 to see the differences.
 
If you want to use the constants above you first generate the corresponding hpp file with modifying the makefile as in previous section, and then add the corresponding include directive :
 
If you want to use the constants above you first generate the corresponding hpp file with modifying the makefile as in previous section, and then add the corresponding include directive :
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
// C++
 
// C++
 
#include <com/sun/star/sheet/CellFlags.hpp>
 
#include <com/sun/star/sheet/CellFlags.hpp>
</source>
+
</syntaxhighlight>
 
in your C++ code. Note that with this include directive you can directly write something like  
 
in your C++ code. Note that with this include directive you can directly write something like  
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
// C++
 
// C++
 
VALUE | DATETIME
 
VALUE | DATETIME
</source>
+
</syntaxhighlight>
 
instead of  
 
instead of  
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
// C++
 
// C++
 
CellFlags_VALUE | CellFlags_DATETIME
 
CellFlags_VALUE | CellFlags_DATETIME
</source>
+
</syntaxhighlight>
 
as seen previously.
 
as seen previously.
  
Line 1,088: Line 1,088:
 
===Converting Sequences into Array===
 
===Converting Sequences into Array===
 
Because it exists a correponding member function this conversion is very easy :
 
Because it exists a correponding member function this conversion is very easy :
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
//Listing 27 Conversion Example
 
//Listing 27 Conversion Example
 
// C++
 
// C++
Line 1,094: Line 1,094:
 
sal_Int32 *table;
 
sal_Int32 *table;
 
table = SetOfInt.getArray();
 
table = SetOfInt.getArray();
</source>
+
</syntaxhighlight>
 
If you read carefully to this point, this code is familiar for you : it's drawn from Listing 4 and then already explained.
 
If you read carefully to this point, this code is familiar for you : it's drawn from Listing 4 and then already explained.
 
===Converting Sequence of Sequence into Array===
 
===Converting Sequence of Sequence into Array===
 
This problem has to be solved. We will use this kind of conversion later (see chapter 14). We first give two subprograms, to print out and to convert :
 
This problem has to be solved. We will use this kind of conversion later (see chapter 14). We first give two subprograms, to print out and to convert :
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
//Listing 28 Sequence of Sequence into 1D array
 
//Listing 28 Sequence of Sequence into 1D array
 
//C+
 
//C+
Line 1,127: Line 1,127:
 
return table1D;
 
return table1D;
 
}
 
}
</source>
+
</syntaxhighlight>
 
Using these sub is easy : it can be done like that :
 
Using these sub is easy : it can be done like that :
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
//Listing 29 Using the conversion
 
//Listing 29 Using the conversion
 
//C+
 
//C+
Line 1,156: Line 1,156:
 
....
 
....
 
delete table;
 
delete table;
</source>
+
</syntaxhighlight>
 
which gives us :
 
which gives us :
 
<pre>
 
<pre>
Line 1,170: Line 1,170:
 
</pre>
 
</pre>
 
Converting a sequence of sequence directly in an 2D array is not an easy task because the compiler has to know the size of the second index before compiling. At first something like  
 
Converting a sequence of sequence directly in an 2D array is not an easy task because the compiler has to know the size of the second index before compiling. At first something like  
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
//Listing 30 Array2D conversion
 
//Listing 30 Array2D conversion
 
// C++
 
// C++
Line 1,180: Line 1,180:
 
return table2D;
 
return table2D;
 
}
 
}
</source>
+
</syntaxhighlight>
 
seems interesting but let's see if that works out. A first idea is to write something like :
 
seems interesting but let's see if that works out. A first idea is to write something like :
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
//Listing 31 Wrong code for  conversion
 
//Listing 31 Wrong code for  conversion
 
// C++
 
// C++
Line 1,192: Line 1,192:
 
}
 
}
 
delete table2;
 
delete table2;
</source>
+
</syntaxhighlight>
 
but the compiler is unable to calculate table2[i][j] here. For that it has to evaluate the expression i*jMax+j but has no knowledge on jMax !!
 
but the compiler is unable to calculate table2[i][j] here. For that it has to evaluate the expression i*jMax+j but has no knowledge on jMax !!
  
 
===More Abstractions with STL===
 
===More Abstractions with STL===
 
If you plan to use C++ you will certainly use the STL extensively. We begin first by conversions. Here is the easier one :
 
If you plan to use C++ you will certainly use the STL extensively. We begin first by conversions. Here is the easier one :
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
//Listing 32 Converting a Sequence of Sequence into a vector
 
//Listing 32 Converting a Sequence of Sequence into a vector
 
// C++
 
// C++
Line 1,210: Line 1,210:
 
     return v;
 
     return v;
 
}
 
}
</source>
+
</syntaxhighlight>
 
My start point for achieving this code was Eric Ethler's code presented [[CompleteAddIn#Transforming_an_Array_into_Sequence_of_Sequence|here]]. This code is again easy to use :
 
My start point for achieving this code was Eric Ethler's code presented [[CompleteAddIn#Transforming_an_Array_into_Sequence_of_Sequence|here]]. This code is again easy to use :
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
//Listing 33 Using the previous Convertion
 
//Listing 33 Using the previous Convertion
 
// C++
 
// C++
Line 1,245: Line 1,245:
 
return 0;
 
return 0;
 
}
 
}
</source>
+
</syntaxhighlight>
 
We give now three other conversions (see also [[CompleteAddIn#Transforming_an_Array_into_Sequence_of_Sequence|here]])
 
We give now three other conversions (see also [[CompleteAddIn#Transforming_an_Array_into_Sequence_of_Sequence|here]])
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
//Listing 34 Converting Utilities with Template
 
//Listing 34 Converting Utilities with Template
 
// C++
 
// C++
Line 1,286: Line 1,286:
 
     return ss;
 
     return ss;
 
}
 
}
</source>
+
</syntaxhighlight>
 
One way to use it is for instance :
 
One way to use it is for instance :
<source lang="cpp">
+
<syntaxhighlight lang="cpp">
 
//Listing 35 Converting Utilities with Template
 
//Listing 35 Converting Utilities with Template
 
//C++
 
//C++
Line 1,300: Line 1,300:
 
cout<<endl;
 
cout<<endl;
 
}
 
}
</source>
+
</syntaxhighlight>
 
Because there is a lot of algorithms based on STL I think these utilities will be very helpfull.
 
Because there is a lot of algorithms based on STL I think these utilities will be very helpfull.
  
Line 1,312: Line 1,312:
 
* [[Uno/Article/Multi-Thread Programming | Multi-Thread Programming]]
 
* [[Uno/Article/Multi-Thread Programming | Multi-Thread Programming]]
 
* To learn C++ : [http://www.smart2help.com/e-books/ C++ e-books]
 
* To learn C++ : [http://www.smart2help.com/e-books/ C++ e-books]
* [http://en.wikibooks.org/wiki/Programming:Data_Structures Wiki on C++ Data Structures]
+
* [https://en.wikibooks.org/wiki/Programming:Data_Structures Wiki on C++ Data Structures]
 
* [[Uno/Binary/Analysis/String_Performance|String Performance]]
 
* [[Uno/Binary/Analysis/String_Performance|String Performance]]
* Writing a Program to Control OpenOffice.org, by Franco Pingiori — [http://www.linuxjournal.com/article/8550 Part 1] and [http://www.linuxjournal.com/article/8608 Part 2], Linux Journal
+
* Writing a Program to Control OpenOffice.org, by Franco Pingiori — [https://www.linuxjournal.com/article/8550 Part 1] and [https://www.linuxjournal.com/article/8608 Part 2], Linux Journal
  
 
[[Category:Tutorial]]
 
[[Category:Tutorial]]
 
[[Category:Cpp]]
 
[[Category:Cpp]]
 
[[Category:Uno]]
 
[[Category:Uno]]

Latest revision as of 14:27, 24 August 2022

doc OOo


Edit-find-replace.png This article should be checked for accuracy and conformity to style.

The UNO C++ Language

The aim of this chapter is to explain peculiarities of the C++ language in the UNO environment and not to provide skills on traditional C++. To put it differently, I want to give here the UNO/C++ background, quite helpful in getting us started. You can find e-Books on C++ here.

See also Understanding Uno, Objects, Interfaces, and Services and OOoBasic UNO Guide for a start with UNO.

Our starting Example : Simple Binaries (Executable)

We want now to start with a SDK example. The purpose of the example presented is to create an executable which interacts with Apache OpenOffice. We can imagine two kind of interactions : direct interaction with OpenOffice or interaction with one of AOO's shared library. We focus on this second case where the makefile is simpler. The shared library involved is then cppuhelper.uno.so (cppuhelper.uno.dll under Windows). Former case will be examined later. I assume (I know nobody of the SDK team) this example is given to provide the simplest example we can do with the SDK. This is the Lifetime example: see at “<SDK_Folder>/examples/DevelopersGuide/ProfUNO/Lifetime”

Before diving into the examples, you will need to set up your programming environment so you can create UNO programs. What's required depends on what platform you're working. This is shown in the first example with LINUX platform. To check this example you only have to launch the makefile :

Documentation linux.png
cd <SDK_Folder>
./setsdkenv_unix
cd examples/DevelopersGuide/ProfUNO/Lifetime
make
make ProfUnoLifetime.runexe

The last command line only launch the binary executable “ProfUnoLifetime” which interact with cpphelper.uno.so (cppuhelper.uno.dll under Windows) even if Apache OpenOffice is not running. This example creates and releases an object, nothing more. The constructor and destructor of the object only write out a message. Its little size allows us to give its code here:

// Listing 1 First Example (from SDK)
// C++
#include <stdio.h>
#include <cppuhelper/weak.hxx>
 
class MyOWeakObject : public ::cppu::OWeakObject
{
public:    
MyOWeakObject() 
{ 
fprintf( stdout, "constructed\n" ); 
}    
~MyOWeakObject() 
{ 
fprintf( stdout, "destructed\n" ); 
}
};
 
void simple_object_creation_and_destruction()
{    
// create the UNO object    
com::sun::star::uno::XInterface * p = new MyOWeakObject(); 
 
// acquire it, refcount becomes one    
p->acquire();    
fprintf( stdout, "before release\n" ); 
 
// release it, refcount drops to zero    
p->release();    
fprintf( stdout, "after release\n" );
}
int main( char * argv[] )
{    
simple_object_creation_and_destruction();    
return 0;
}

The two methods acquire and release will be encountered later. What exactly they do is not important for the moment. This example shows us how to write a class which inherits from another class, how to write and call methods and how to instantiate the class. All the listings given below only need to modify this C++ code, compile it and run it. You can therefore use the same makefile by possibly changing the name of the source file (tackled in next section).

Types

The UNO types are given in the table below :

UNO Types
UNO Type description Java C++ Basic
char 16-bit unicode character type char sal_Unicode -
boolean boolean type; true and false boolean sal_Bool Boolean
byte 8-bit ordinal type byte sal_Int8 Integer
short signed 16-bit ordinal type short sal_Int16 Integer
unsigned short unsigned 16-bit ordinal type - sal_uInt16 -
long signed 32-bit ordinal type int sal_Int32 Long
unsigned long unsigned 32-bit type - sal_uInt32 -
hyper signed 64-bit ordinal type long sal_Int64 -
unsigned hyper unsigned 64-bit ordinal type - sal_uInt64 -
float processor dependent float float float (IEEE float) Single
double processor dependent double double double (IEEE double) Double

The UNO's column represents all the types you can find in the specifications files : IDL files. We describe IDL files later (see chapter 10). The C++ column is what we are interested in when we program with this language. If you want to check the different programs given in this chapter, you can use the <OpenOffice.org1.1_SDK>/examples/DevelopersGuide/ProfUNO/Lifetime example. Replace object_lifetime.cxx completely with the listing below (don't forget to save the old file)

// Listing 2 A short UNO Program 
// C++
#include <stdio.h>
#include <cppuhelper/bootstrap.hxx>
 
main( ) {
	sal_Int32 var1;
	var1 = 34;
	printf("The var1 value is : %d\n",var1);
   	return 0;
}

then launch

make ALL
make ProfUnoLifetime.runexe

and it works. Don't forget ./setsdkenv_unix (only one time) on Linux and the corresponding command (setsdkenv_windows.bat) on Windows.

Sequences

We can find also good materials in Developer's guide on Sequence. A sequence is an abstract view of a set of UNO types with a variable number of elements. As first example, we give a very simple program:

// Listing 3  UNO Sequences
// C++
#include <stdio.h>
#include <cppuhelper/bootstrap.hxx>
#include <com/sun/star/uno/Sequence.hxx>
using namespace com::sun::star::uno;
 
main( ) {
	Sequence < sal_Int32 > SetOfInt(5);
	//var1 = 34;
	SetOfInt[2]=44;
	printf("The value is : %d\n",SetOfInt[2]);
    return 0;
}

The important things to notice are as follows:

  • the type of each element of the set is put between angular brackets: "<" and ">". In the example above sal_int32 is the type.
  • declaration of sequence is done with parentheses "(" and ")" and the number of elements of the sequence between them. In the example above a sequence of five sal_Int32 elements is declared.
  • accessing elements of the sequence is done with "[" and "]" and an index between them (generally called subscript operator). This allows us to say that sequences are referenced like arrays. But they are different in some way, for instance they don't have a fixed size.
  • We have to include Sequence.hxx file in a program when using Sequence. Note that this file is provided with the SDK and this is not always the case for all hxx files (some of them have to be reconstructed).

We have to use the correct namespace with adding "using namespace …" If you don't use this statement, you have to write com::sun::star::uno::Sequence instead of Sequence. A Sequence can be created with arbitrary UNO type but not with other types. The object SetOfInt has many methods. We give an example to show some of them:

// Listing 4 Examples of using Sequence Methods
// C++
#include <stdio.h>
#include <cppuhelper/bootstrap.hxx>
#include <com/sun/star/uno/Sequence.hxx>
using namespace com::sun::star::uno;
 
main( ) {
	Sequence < sal_Int32 > SetOfInt(5);
	sal_Int32 *table;
	SetOfInt[2]=44;
	printf("The value is : %d\n",SetOfInt[2]);
	// Tests whether the sequence has elements, i.e. elements count is greater than zero
	if (SetOfInt.hasElements()) printf("Set not empty\n");
	// Gets a pointer to elements array for reading and writing. If the sequence 
	//  has a length of 0, then the returned pointer is undefined
	table = SetOfInt.getArray();
	table[4]=78;
	printf("The value is : %d\n",SetOfInt[4]); // prints out 78
	SetOfInt.realloc(7);
	printf("New length : %d\n",SetOfInt.getLength()); // prints out 7
	return 0;
}

The comments explain what is printed out when executing this example. The method realloc is particularly important: it allows the size of set to change.

Let us focus on using sequences in function or as parameter. An example is again more descriptive than a long text:

// Listing 5 Sequence and Parameters 
// C++
// function
Sequence < sal_Int32 > initSequence(){
	sal_Int32 sourceArray[5]={1,2,3,4,5};
	Sequence < sal_Int32 > SeqOfInt(sourceArray,5);
	return SeqOfInt;
}
// reference parameter
void initSequence2(Sequence < sal_Int32 > &SeqOfInt ) {
	sal_Int32 sourceArray[4]={1,2,3,4};
	Sequence < sal_Int32 > SeqOfInt2(sourceArray,4);
	SeqOfInt=SeqOfInt2;
}

An obvious call could be :

// Listing 6 Sequence and Parameters (following) 
// C++
	SetOfInt = initSequence();
	printf("New length : %d\n",SetOfInt.getLength()); // prints out 5
	initSequence2(SetOfInt);
	printf("New length : %d\n",SetOfInt.getLength()); // prints out 4

We cannot leave this section without adding that operators == and != are available with sequences. Note also that "toUnoSequence()", "getCppuSequenceType()" and "getCharSequenceCppuType()" are also member functions.

Passing a sequence into a function by value is, like a vector, somewhat inefficient because the function must make a copy of all elements. It's better to use a constant reference as shown below:

// Listing 7 The Constant Reference method
//C++
#include <iostream>
#include <cppuhelper/bootstrap.hxx>
#include <com/sun/star/uno/Sequence.hxx>
using namespace com::sun::star::uno;
using namespace std;
 
// Passing a Sequence by value using the Constant Reference method
void avoidCopy(const Sequence< double > &ConstRef){
	// ConstRef[2]=6.7; would fail here
	for(int i=0;i<ConstRef.getLength();i++)
           cout<<ConstRef[i]<<" ";
	cout<<endl;
 
}
 
main( ) {
    Sequence < double > demo(5);
    demo[0]=1.1;
    demo[1]=2.1;
    demo[2]=3.1;
    demo[3]=4.1;
    demo[4]=5.1;
    avoidCopy(demo);
    return 0;
}

See other material in Developer's Guide (UNO C++ Binding).

Strings

In C, a string is simply an array of characters that always includes a binary zero (often called the null terminator) as its final array element. UNO/C++ API manages strings with two classes: OUString and OString. The former uses Unicode characters.

STRING UNO Type
UNO Type description Java C++ Basic
string String of 16-bit unicode characters Java.lang.string ::rtl::OUString String

But, if you want to use ASCII characters the latter class is for you.

OUString and OString

OUString and OString classes are designed for UNO programmers. Only OString can be used with a standard C printf. To put it differently OString is nearer to the common C ASCII strings (array of characters) than OUString (which is an array of Unicode). But all strings managed by UNO API are OUString. That means, if you want to see something in the console, you have to convert OUString to OString. If you ask something to the user and want to pass it to UNO API, you have to convert OString to OUString. Then if you want to use the console (in general for testing) you have to learn first both conversions.

OUString to OString

If OUStr is a OUString object, we give this example for conversion:

// Listing 8 Converting OUString into OString
// C++
#include <rtl/string.hxx>
 
	OString o = OUStringToOString( OUStr, RTL_TEXTENCODING_ASCII_US );
	printf( "Conversion result : %s\n", o.pData->buffer );

OString to OUString

The inverse conversion is easy too :

// Listing 9 Converting OString into OUString
// C++
	OUString foo;
	foo = OUString::createFromAscii("Hi everybody");

Here is a complete conversion example:

// Listing 10 A complete Example
// C++
#include <stdio.h>
#include <cppuhelper/bootstrap.hxx>
#include <rtl/string.hxx>
using namespace rtl;
 
main( ) {
	OUString OUStr;
	OUStr = OUString::createFromAscii("Hi everybody");
	OString OStr = OUStringToOString( OUStr, RTL_TEXTENCODING_ASCII_US );
	printf( "OUStr was : %s\n", OStr.pData->buffer );
	return 0;
}

We see that a rtl namespace has to be used. If not, please replace OUString by ::rtl::OUString. OUString and OString objects are class type variables, and then the operations that can be performed on O(U)Strings take the form

 
        O(U)StringVariable.operation(argumentList)

For example, if string1 and string2 are variables of type OUString, then

 
        string1.compareTo(string2)

can be used to compare both strings. A function like compareTo(), which is part of the O(U)String-class is called a member function. The O(U)String class offers a large number of these member functions, as well as extensions of some well-known operators, like the assignment (=) and the comparison operator (==). These operators and functions are discussed in the following sections. The OUString and OString methods are similar: we give a complete example which shows some of them:

// Listing 11 A more complete Example
// C++
#include <stdio.h>
#include <cppuhelper/bootstrap.hxx>
#include <rtl/string.hxx>
using rtl::OUString;
using rtl::OString;
 
main( ) {
	OUString OUStr1,OUStr2;
	OString OStr1, OStr2;
	OStr1="Hi every body";
	OStr2="every body";
	OUStr1 = OUString::createFromAscii("Hi everybody");
	OUStr2 = OUString::createFromAscii("Hi everybody");
	// Returns the length of this string
	printf("Length : %d\n",OUStr1.getLength()); // prints out 13
	// Compares two strings
	printf("CompareTo : %d\n",OUStr1.compareTo(OUStr2)); // prints out 0
	// Compares two strings
        // serviceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("my_module.MyService2") );
	printf("equals : %d\n",OUStr1.equals(OUStr2)); // prints out 1
	if (OUStr1.equals(OUStr2)) printf("OK\n");// prints out OK
	// Compares two strings
	printf("CompareToAscii : %d\n",OUStr1.compareToAscii(OStr1)); // prints out 0
	// Compares two strings with a maximum count of characters
	printf("CompareToAscii : %d\n",OUStr1.compareToAscii(OStr1),10); // prints out 0
	// Perform a comparison of a substring in this string
	// is "every body" in position 3 of OUStr1 ?
	if (OUStr1.match(OUString::createFromAscii("everybody"),3))
		printf("match : OK\n"); //prints out match : OK
	// Perform a comparison of a substring in this string
	if (OUStr1.matchAsciiL(OStr2,OStr2.getLength(),3))
		printf("matchAsciiL: OK\n");
	// Returns the float value from this string
	OUStr2 = OUString::createFromAscii("1.675");
	printf("toFloat : %f\n",OUStr2.toFloat()); // prints out 1.675000
	// Value Of :
	OUStr1 = OUStr1.valueOf((float)1.56);
	OStr1 = OUStringToOString( OUStr1, RTL_TEXTENCODING_ASCII_US );
	printf( "Value of : %s\n", OStr1.pData->buffer );
	// concat
	OUStr2=OUStr2.concat(OUString::createFromAscii(" ..."));
	OStr1 = OUStringToOString( OUStr2, RTL_TEXTENCODING_ASCII_US );
	printf( "concat is : %s\n", OStr1.pData->buffer );
	return 0;
}

We can also see in this program how the concat method (three last lines) is used. The toFloat() conversion method is not alone: toBoolean(), toChar(), toInt32(), toInt64(), toDouble(), toAsciiLowerCase() and toAsciiUpperCase() exist also. Now we terminate with presenting some other methods (see C++ material):

String methods
Methods
indexOf( sal_Unicode ch, sal_Int32 fromIndex = 0 ) Returns the index within this string of the first occurrence of the specified character, starting the search at the specified index
sal_Int32 hashCode() Returns a hashcode for this string
sal_int32 lastIndexOf(sal_Unicode ch ) Returns the index within this string of the last occurrence of the specified character, searching backward starting at the end
sal_Int32 lastIndexOf(sal_Unicode ch, sal_Int32 fromIndex ) Returns the index within this string of the last occurrence of the specified character, searching backward starting at the specified index
sal_Int32 lastIndexOf(const OUString & str ) Returns the index within this string of the last occurrence of the specified substring, searching backward starting at the end
OUString copy(sal_Int32 beginIndex, sal_Int32 count ) OUString copy(sal_Int32 beginIndex ) Returns a new string that is a substring of this string
OUString replaceAt(sal_Int32 index, sal_Int32 count, const OUString & newStr ) Returns a new string resulting from replacing n = count characters from position index in this string with newStr
OUString replace(sal_Unicode oldChar, sal_Unicode newChar ) Returns a new string resulting from replacing all occurrences of oldChar in this string with newChar
OUString trim() Returns a new string resulting from removing white space from both ends of the string
OUString getToken(sal_Int32 token, sal_Unicode cTok, sal_Int32 & index ) Returns a token in the string

I cannot close this section without giving a code found in AOo source /OOB680_m5/registry/source/regimpl.cxx

//Listing 11-b Printing out an OUString
// C++
void printString(rtl::OUString const & s) {
    printf("\"");
    for (sal_Int32 i = 0; i < s.getLength(); ++i) {
        sal_Unicode c = s[i];
        if (c == '"' || c == '\\') {
            printf("\\%c", static_cast< char >(c));
        } else if (s[i] >= ' ' && s[i] <= '~') {
            printf("%c", static_cast< char >(c));
        } else {
            printf("\\u%04X", static_cast< unsigned int >(c));
        }
    }
    printf("\"");
}

If you want to see the content of an OUString with standard output, you have only to convert it to OString :

//Listing 11-c Printing out an OUString with standard C++ output
// C++
  OUString OUStr  = OUString::createFromAscii( "Hello" );
  OString   OStr  = OUStringToOString ( OUStr,RTL_TEXTENCODING_UTF8);
  cout <<  Ostr << endl;

File Path

Documentation linux.png Linux related content : the file paths are OS-dependent. To remove this dependency, UNO use URL and a way to transform a file path to an URL. We show an example now
// Listing 12 UNO URL
// C++
// Don't forget #include <osl/file.hxx>
	OUString sDocUrl;
    osl::FileBase::getFileURLFromSystemPath(
                 OUString::createFromAscii("/home/smoutou/edt.sxd"),sDocUrl);
// Windows C++ to check
//	osl::FileBase::getFileURLFromSystemPath(
//			  OUString::createFromAscii("\"C:\\My Documents\\tata.sxc\""),sDocUrl);

A complete example is given in the below listing :

// Listing 13 Using URL
// C++
#include <stdio.h>
#include <cppuhelper/bootstrap.hxx>
#include <osl/file.hxx>
using rtl::OUString;
using rtl::OString;
using namespace osl;
 
main( ) {
	OUString sDocUrl;
	OString toPrintOut;
   	osl::FileBase::getFileURLFromSystemPath(
                 OUString::createFromAscii("/home/smoutou/edt.sxd"),sDocUrl);
	toPrintOut = OUStringToOString( sDocUrl, RTL_TEXTENCODING_ASCII_US );
	printf( "URL is : %s\n", toPrintOut.pData->buffer );
	// prints out URL is : file:///home/smoutou/edt.sxd
	return 0;
}

which shows how to use the conversion. Remember that we work with UNO and therefore the URL is an OUString.

Documentation windows.png Only file paths have to be changed to transform these programs into Windows programs

SDK Example

Here is some code provided by SDK :

// Listing 14 SDK Example
// C++
#include <stdio.h>
#include <rtl/ustrbuf.hxx>
#include <rtl/string.hxx>
 
using rtl::OUString;
using rtl::OUStringBuffer;
using rtl::OString;
 
int main( int argc, char * argv [] )
{
    // string concatination
 
    sal_Int32 n = 42;
    double pi = 3.14159;
 
    // give it an initial size, should be a good guess.
    // stringbuffer extends if necessary
    OUStringBuffer buf( 128 );
 
    // append an ascii string
    buf.appendAscii( "pi ( here " );
 
    // numbers can be simply appended
    buf.append( pi );
 
    // lets the compiler count the stringlength, so this is more efficient than
    // the above appendAscii call, where length of the string must be calculated at
    // runtime
    buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" ) multiplied with " ) );
    buf.append( n );
    buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" gives ") );
    buf.append( (double)( n * pi ) );
    buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "." ) );
 
    // now transfer the buffer into the string.
    // afterwards buffer is empty and may be reused again !
    OUString string = buf.makeStringAndClear();
 
    // I could of course also used the OStringBuffer directly
    OString oString = rtl::OUStringToOString( string , RTL_TEXTENCODING_ASCII_US );
 
    // just to print something
    printf( "%s\n" ,oString.getStr() );
    return 0;
}

This example shows an other way to use OUString, OString and buffer.

For performance analysis see Some String Performance Thoughts

Sequence of Strings

Sequence has been tackled in a previous section. If you want to construct a Sequence of string (useful in list box ...) have a look on this piece of code :

// Listing 15 An Example of Sequence of Strings
// C++
// Sequence of string
#include <rtl/string.hxx>
// Don't forget to add #include <com/sun/star/uno/Sequence.hxx>
// Don't forget to add using namespace com::sun::star::uno;
	Sequence<OUString>seqStrlistItems(2);
	seqStrlistItems[0]=OUString::createFromAscii("Item1");
	seqStrlistItems[1]=OUString::createFromAscii("Item2");
 
// retrieve them and prints out
	for (int i=0;i<seqStrlistItems.getLength();i++){
		OString toPrintOut = OUStringToOString(seqStrlistItems[i],RTL_TEXTENCODING_ASCII_US);
		printf("-- %s\n",toPrintOut.pData->buffer);
	}

This code prints out in the shell console :

-- Item1
-- Item2
[smoutou@p3 Lifetime]$ 

It is easy to understand and therefore I have nothing more to say about it.

Exercise on Sequence of Strings

Write and test the following "convert2SeqOUStrInDEBUGMODE" function with a sequence of "sal_Int8" as parameter and which returns a sequence of Strings in a format like the dump method of the old "debug" of DOS. This format will be used here, but without this function.

Solution : here is the corresponng function code

Sequence< OUString > convert2SeqOUStrInDEBUGMODE(Sequence < sal_Int8 > seqBytes){
  sal_Int8 Hexa[16]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
  sal_Int32 lin,col;
  sal_Char line[80];
  sal_Int32 len,sequenceSize,index;
  len=seqBytes.getLength();
  sequenceSize=(len>>4)+2;
  if ((len&0XFFF0)==len) sequenceSize--; //if len%16==0
  Sequence< OUString > SeqOUStr(sequenceSize);
  // First line with length 
  SeqOUStr[0] = OUString::createFromAscii("Length:")+
                OUString::valueOf((sal_Int32) seqBytes.getLength());
  len = len&0XFFF0; // remove the modulo 16
  for(lin=0;lin<len;lin=lin+16){
      for(col=0;col<16;col++){
        line[3*col]=Hexa[((unsigned char)seqBytes[lin+col])>>4];
	line[3*col+1]=Hexa[seqBytes[lin+col]&0x0F];
	line[3*col+2]=' ';
        if ((seqBytes[lin+col]<128)&&(seqBytes[lin+col]>20)) line[50+col]=seqBytes[lin+col];
        else line[50+col]='.';
      } /* end of for */
      line[66]=0; /* end of cstring...*/
      line[48]=' ';line[49]=' ';
  // ready to add the OUString in Sequence
      if ((lin%16)==0) index = lin/16+1; else index=lin/16+2;
      SeqOUStr[index]=OUString::createFromAscii(line);
  } /* end of for */ 
  // the last line is more complicated because not complete
  // we only keep modulo
  len=seqBytes.getLength()&0x000F;
  if (len>0) { // only a line here if non-empty
  for (lin=0;lin<len;lin++){
    col=lin;
    line[3*col]=Hexa[((unsigned char)seqBytes[lin])>>4];
    line[3*col+1]=Hexa[seqBytes[lin]&0x0F];
    line[3*col+2]=' ';
    if ((seqBytes[lin]<128)&&(seqBytes[lin]>20)) line[50+col]=seqBytes[lin];
    else line[50+col]='.';
  }
  // we complete the line
  for (++col;col<16;col++){
	line[3*col]=' ';line[3*col+1]=' ';line[3*col+2]=' ';line[50+col]=' ';
  }
  line[66]=0; /* end of string...*/
  line[48]=' ';line[49]=' ';
  // ready to add the OUString in Sequence
  SeqOUStr[lin/16+2]=OUString::createFromAscii(line);
  } //end if
  return SeqOUStr;
}

and now how this function can be used :

sal_Int8 sourceArray[32]={1,22,23,24,55,56,57,8,9,10,11,12,13,14,15,16,17,18,19,61,62,-32,-33,-34,-35,26,127,-31,29,56,23,67};
        Sequence < sal_Int8 > seqBytes(sourceArray,32);
	Sequence < OUString > seqOUStr=convert2SeqOUStrInDEBUGMODE(seqBytes);
	printf("%s\n",OUStringToOString( seqOUStr[0], RTL_TEXTENCODING_ASCII_US ).pData->buffer);
	printf("%s\n",OUStringToOString( seqOUStr[1], RTL_TEXTENCODING_ASCII_US ).pData->buffer);
	printf("%s\n",OUStringToOString( seqOUStr[2], RTL_TEXTENCODING_ASCII_US ).pData->buffer);

In our introspection tool we need also this format but in one string. It's easy to write the corresponding code :

OUString convert2OUStrInDEBUGMODE(Sequence < sal_Int8 > seqBytes){
  Sequence <OUString> SeqOUStr = convert2SeqOUStrInDEBUGMODE(seqBytes);
  OUString OUStr;
  for(sal_Int32 i=0;i<SeqOUStr.getLength();i++)
    OUStr = OUStr+SeqOUStr[i]+OUString::createFromAscii("\n");
  return OUStr;
}

which can be used with :

sal_Int8 sourceArray[32]={1,22,23,24,55,56,57,8,9,10,11,12,13,14,15,16,17,18,19,61,62,-32,-33,-34,-35,26,127,-31,29,56,23,67};
        Sequence < sal_Int8 > seqBytes(sourceArray,32);
 
        OUString OUStr=convert2OUStrInDEBUGMODE(seqBytes);
        printf("%s\n",OUStringToOString( OUStr, RTL_TEXTENCODING_ASCII_US ).pData->buffer);

Any

We can find also good materials in Developer's guide on Any type. Any is easy to use only with <<= and >>= operators and we then often use intermediate variables. We can use also the build-in “makeAny” function :

// Listing 16 makeAny Example
// C++
Any any = makeAny((long) 1000);

We give first an example above :

//Listing 17 Any Example
// C++
#include <stdio.h>
#include <cppuhelper/bootstrap.hxx>
#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/uno/Sequence.hxx>
using rtl::OUString;
using rtl::OString;
using com::sun::star::uno::Any;
using namespace com::sun::star::uno;
using namespace rtl;
 
main( ) {
	Any any,any2;
	sal_Int32 n=5,n2=18;
	any <<= n;
	// Gets the type name of the set value
	OUString OUStr = any.getValueTypeName();
	OString OStr = OUStringToOString( OUStr, RTL_TEXTENCODING_ASCII_US );
	printf( "Any type : %s\n", OStr.pData->buffer );// prints out Any type : long
	// Tests if any contains a value
	if (any.hasValue()) printf("Any has a value\n");// prints out Any has a value
	// Clears this any. If the any already contains a value, that value will be destructed and
	// its memory freed. After this has been called, the any does not contain a value.
	any.clear();
	if (any.hasValue()) printf("Any has a value\n");// prints out nothing
	any <<= n2;
	any2 <<= OUStr;
	// Unequality operator: compares two anys. The values need not be of equal type,
	// e.g. a short integer is compared to a long integer
	if (any != any2) printf("Two different any\n");
 
	Sequence< Any> aValues(2);
	aValues[0] <<= (float) 1.1; aValues[1] <<= OUString::createFromAscii("Text");
	aValues[1] >>= OUStr;
	OStr = OUStringToOString( OUStr, RTL_TEXTENCODING_ASCII_US );
	float real;
	aValues[0] >>= real;
	printf("Seq - length : %d val : %f val %s\n",aValues.getLength(),real,OStr.pData->buffer);
	return 0;
}

This program prints out :

Any type : long
Any has a value
Two different any
Seq - length : 2 val : 1.100000 val Text

Another important problem is a sequence of sequence of Any : we give now a piece of code without explanation :

// Listing 18 Sequence of Sequence of Any
// C++
Sequence< Sequence< Any > > aValues(2); 
Sequence< Any > aValues2(2);
aValues2[0] <<=  (double) 1.1; aValues2[1] <<= OUString::createFromAscii("Hello");
aValues[0] = aValues2;
aValues2[0] <<=  (double)2.2; aValues2[1] <<= OUString::createFromAscii("Hi");
aValues[1] = aValues2;

This code uses two sequences. I have not found an other simpler way to do that. If anybody has a more straightforward solution, I would be happy learn about it. If it is possible to access directely a value in a 2D array but I found only one means using an intermediate sequence (avalues2) in the case of sequence of sequence.

Files

Documentation linux.png

We now want to create a textfile named "demo.txt". Here is the code to do this :

// Listing 19 A little Example manipulating Files
// C++
#include <stdio.h>
#include <cppuhelper/bootstrap.hxx>
#include <osl/file.hxx>
 
using rtl::OUString;
using rtl::OString;
using namespace osl;
 
main( ) {
	OUString FileName;
	sal_Int8 tab[25]="Hi every body\n";
	sal_uInt64 nb;
	osl::FileBase::getFileURLFromSystemPath(
                 OUString::createFromAscii("/home/smoutou/demo.txt"),FileName);
	File myfile(FileName);
	myfile.open(OpenFlag_Write);
	myfile.write(tab,(sal_uInt64)16,nb);
	printf("%d bytes are written\n",nb);
	myfile.close();
	return 0;
}
Documentation note.png The method open is not described in C++ documentation !!! I have found it while reading the “file.hxx” header file.

The flag you can pass to the "open" method are : OpenFlag_Write, OpenFlag_Read, OpenFlag_Create. The " using namespace osl;" is obligatory even if the compiler doesn't complain without. When a file is open, you can use the methods above :

// C++
// Write a number of bytes to a file
write( const void * pBuffer, sal_uInt64 uBytesToWrite, sal_uInt64 & rBytesWritten );
 
// Read a number of bytes from a file
read( void * pBuffer, sal_uInt64 uBytesRequested, sal_uInt64 & rBytesRead );
 
// Read a line from a file
ReadLine( ::rtl::ByteSequence & aSeq );
 
// Test if the end of a file is reached
isEndOfFile( sal_Bool * pIsEOF );
 
// Retrieve the current position of the internal pointer of an open file
getPos( sal_uInt64 & uPos );
 
// Set the internal position pointer of an open file. 
setPos( sal_uInt32 uHow, sal_Int64 uPos );

There are other possibilities : move, remove, copy... See the documentation or read the file.hxx file.

See « Streaming interfaces » for an other way to use files.

Threads

It would be great to use the Thread Class but it's so badly documented that we begin with process instead thread. Starting from an example posted in the forum Working with a Spreadsheet Document in C++ (by lirincy). This example gives a working code to start AOO if not started when launching a binary executable. We remove what was not usefull for us and give two examples.

Documentation linux.png
// Listing 20 A Process Example
// C++
#include <stdio.h>
#include <cppuhelper/bootstrap.hxx>
#include <osl/process.h>
#include <osl/file.hxx>
 
using rtl::OUString;
using rtl::OString;
 
main( ) {
// Don't forget to add #include <osl/process.h>
	oslProcess hProcess = NULL;
// Don't forget to add #include <osl/file.hxx>
	OUString FileURL;
	osl::FileBase::getFileURLFromSystemPath(
	OUString::createFromAscii("/home/smoutou/demo"),
		FileURL
	);
	oslProcessError osl_error = osl_executeProcess(
	 FileURL.pData,
	 NULL,
	 0,
	 osl_Process_DETACHED,
	 0, /* osl_getCurrentSecurity() */
	 NULL,
	 NULL,
	 0,
	 &hProcess );
	osl_error = osl_joinProcess(hProcess);
	return 0;
}
Documentation note.png Note that the demo file is an existing binary in /home/smoutou.

If you want to pass something to the launched program see AppArgs variable in the second example :

Documentation linux.png
// Listing 21 A second Process Example
// C++
#include <stdio.h>
#include <cppuhelper/bootstrap.hxx>
#include <osl/process.h>
#include <osl/file.hxx>
 
using rtl::OUString;
using rtl::OString;
 
main( ) {
// Don't forget to add #include <osl/process.h>
	oslProcess hProcess = NULL;
// Don't forget to add #include <osl/file.hxx>
	OUString FileURL;
	osl::FileBase::getFileURLFromSystemPath(
	OUString::createFromAscii("/home/smoutou/demo"),
		FileURL
	);
	OUString AppArgs = OUString::createFromAscii("Arg1");
	oslProcessError osl_error = osl_executeProcess(
	 FileURL.pData,
	 &AppArgs.pData,
	 1,
	 osl_Process_DETACHED,
	 0, /* osl_getCurrentSecurity() */
	 NULL,
	 NULL,
	 0,
	 &hProcess );
	osl_error = osl_joinProcess(hProcess);
 
	return 0;
}

I have tried working with thread but only with C style at the moment (not with using the thread class). Here is my first example code :

Documentation linux.png
// Listing 22 A working Thread Example
// C++
#include <stdio.h>
#include <cppuhelper/bootstrap.hxx>
#include <osl/thread.h>
#include <unistd.h> // LINUX
 
using rtl::OUString;
using rtl::OString;
 
/** wait _nSec seconds.
*/
void thread_sleep( sal_Int32 _nSec )
{
/// print statement in thread process must use fflush() to force display.
	printf("# wait %d seconds. ", _nSec );
	fflush( stdout );
	sleep( _nSec );
	printf("# done\n" );
}
 
void SAL_CALL thread1(void *) {
  while(1) 
	printf("\n thread running");
 
}
 
void SAL_CALL thread2(int *nb){
  while(1) 
	printf("\n thread nb=%d running",*nb);
}
 
main( ) {
// Don't forget to add #include <osl/thread.h>
	oslThread hThread = NULL;
//oslWorkerFunction type : void (SAL_CALL *oslWorkerFunction)(void*); in osl/thread.h
	oslWorkerFunction pFunction = (void (SAL_CALL *)(void*)) thread2;
	int pthreaddata=2;
// create and start the thread2 with 2 as a parameter value
	oslThread hThread2 = osl_createThread(pFunction,(void *) &pthreaddata);
// create and start the thread1 
	hThread = osl_createThread(thread1,NULL);
 
	thread_sleep(2);
	osl_suspendThread(hThread);
	osl_suspendThread(hThread2);
 
	return 0;
}

What is printed out is depending on how the screen is managed by your OS. Under Linux I obtained something like this :

 ...
 thread running
 thread running
 thread running
 thread running# done
 
 thread nb=2 running
 thread nb=2 running
 thread nb=2 running
 thread nb=2 running
 ....

Here you can see the second thread launched writes at first and only when the main sleeping is terminated, thread two is writing out. The other thread primitives can be found in osl/thread.h :

/** Create the thread, using the function-ptr pWorker as
	its main (worker) function. This functions receives in
	its void* parameter the value supplied by pThreadData.
	Once the OS-structures are initialized,the thread starts
	running.
	@return 0 if creation failed, otherwise a handle to the thread
*/
oslThread SAL_CALL osl_createThread(oslWorkerFunction pWorker, void* pThreadData);

/** Create the thread, using the function-ptr pWorker as
	its main (worker) function. This functions receives in
	its void* parameter the value supplied by pThreadData.
	The thread will be created, but it won't start running.
	To wake-up the thread, use resume().
	@return 0 if creation failed, otherwise a handle to the thread
*/
oslThread SAL_CALL osl_createSuspendedThread(oslWorkerFunction pWorker, void* pThreadData);

/** Release the thread handle.
	If Thread is NULL, the function won't do anything.
	Note that we do not interfere with the actual running of
	the thread, we just free up the memory needed by the handle.
*/
void SAL_CALL osl_destroyThread(oslThread Thread);

/** Wake-up a thread that was suspended with suspend() or
	createSuspended(). The oslThread must be valid!
*/
void SAL_CALL osl_resumeThread(oslThread Thread);

/** Suspend the execution of the thread. If you want the thread
	to continue, call resume(). The oslThread must be valid!
*/
void SAL_CALL osl_suspendThread(oslThread Thread);
/** Returns True if the thread was created and has not terminated yet.
	Note that according to this definition a "running" thread might be
	suspended! Also returns False is Thread is NULL.
*/
sal_Bool SAL_CALL osl_isThreadRunning(const oslThread Thread);

/** Blocks the calling thread until Thread has terminated.
	Returns immediately if Thread is NULL.
*/
void SAL_CALL osl_joinWithThread(oslThread Thread);

/** Blocks the calling thread at least for the given number
    of time.
*/
void SAL_CALL osl_waitThread(const TimeValue* pDelay);

For more information you can read Multi-Thread Programming.

To go further : the Enumeration Type Problem

Sometimes we will encounter enumeration values. We have to learn how to resolve the problem. An example will be discussed later but we give it without its context here. The Cell content in Apache OpenOffice Calc is described by an enumeration. How can I know that, is not easy with the previous material, but I want to tackle the problem even if too soon to understand for a first reading.

All types used in programming are described in IDL files. Sometimes these IDL files are used to create hpp/hxx files.

This example is around CellContentType.idl file. Here is the summary of this file where we remove comments :

// Listing 23  CellContentType Enumeration type (IDL File)
// IDL
namespace com{
namespace sun{
namespace star{
namespace table{
enum CellContentType
{
    CellContentType_EMPTY = 0,
    CellContentType_VALUE = 1,
    CellContentType_TEXT = 2,
    CellContentType_FORMULA = 3,
    CellContentType_MAKE_FIXED_SIZE = SAL_MAX_ENUM
};
} // table
} // star
} // sun
} // com

Three tips can be used when using this kind of enumeration :

  • In C++ a corresponding using namespace is necessary

using namespace com::sun::star::table This line can be drawn from the IDL file.

  • In C++ an include directive is necessary
#include <com/sun/star/table/CellContentType.hpp>

The name of the file to include and the path is easy to draw from IDL file.

  • We have to construct the previous hpp file. This is done with adding the red line above in the makefile :
TYPES := \
	com.sun.star.uno.XNamingService \
	com.sun.star.uno.XComponentContext \
	com.sun.star.uno.XWeak \
	com.sun.star.uno.XAggregation \
	com.sun.star.lang.XMain \
	com.sun.star.lang.XMultiServiceFactory \
	com.sun.star.lang.XSingleComponentFactory \
	com.sun.star.lang.XTypeProvider \
	com.sun.star.lang.XComponent \
	com.sun.star.registry.XSimpleRegistry \
	com.sun.star.registry.XImplementationRegistration \
	com.sun.star.bridge.XBridgeFactory \
	com.sun.star.bridge.XUnoUrlResolver \
	com.sun.star.table.CellContentType \
	com.sun.star.container.XHierarchicalNameAccess

After you can use this enumeration without problem like this :

// Listing 24 Enumeration type : an Example
//C++
// To check
// Don't forget to add #include <com/sun/star/table/CellContentType.hpp>
// Don't forget to add "com.sun.star.table.CellContentType \" in the makefile
 
	using namespace com::sun::star::table
	short enumval;
	enumval =  CellContentType_EMPTY;
	switch (enumval){
		case CellContentType_EMPTY : printf("Empty\n");break;
		case CellContentType_VALUE : printf("Numerical Value\n");break;
		case CellContentType_TEXT : printf("Text\n");break;
		case CellContentType_FORMULA : printf("Formula\n");break;
	}

What is shown here is a general SDK's feature : we construct a hpp file starting from an IDL file. This is so important and unexpected for beginners that I will repeat many times these explanations later and more deeply here.

To go further : the Constant Type Problem

Values are not always defined with enumeration types as shown in previous section. Sometimes constants are used when programming with UNO. One example is again tackled later but we want again writes on it now. We first present the corresponding IDL file (as an example)

// Listing 25 CellFlags Constants type : IDL File 
//IDL
module com {  module sun {  module star {  module sheet {
constants CellFlags
{
	const long VALUE = 1;
	const long DATETIME = 2;
	const long STRING = 4;
	const long ANNOTATION = 8;
	const long FORMULA = 16;
	const long HARDATTR = 32;
	const long STYLES = 64;
	const long OBJECTS = 128;
	const long EDITATTR = 256;
};
}; }; }; };

Compare this listing with Listing 23 to see the differences. If you want to use the constants above you first generate the corresponding hpp file with modifying the makefile as in previous section, and then add the corresponding include directive :

// C++
#include <com/sun/star/sheet/CellFlags.hpp>

in your C++ code. Note that with this include directive you can directly write something like

// C++
VALUE | DATETIME

instead of

// C++
CellFlags_VALUE | CellFlags_DATETIME

as seen previously.

Going further with Sequences

We want to give any utilities used later in this document.

Converting Sequences into Array

Because it exists a correponding member function this conversion is very easy :

//Listing 27 Conversion Example
// C++
Sequence < sal_Int32 > SetOfInt(5);
sal_Int32 *table;
table = SetOfInt.getArray();

If you read carefully to this point, this code is familiar for you : it's drawn from Listing 4 and then already explained.

Converting Sequence of Sequence into Array

This problem has to be solved. We will use this kind of conversion later (see chapter 14). We first give two subprograms, to print out and to convert :

//Listing 28 Sequence of Sequence into 1D array
//C+
// Sequence of Sequence is printed out like that :
// toPrint[0][0] toPrint[0][1] toPrint[0][2]...
// toPrint[1][0] toPrint[1][1] toPrint[1][2]...
// ...
// Note that i denotes the first index
void printOutSeqSeq(const Sequence < Sequence < double > > &toPrint){
	cout << "Prints out SeqSeq" << endl;
        for(int i=0;i<toPrint.getLength();i++){
                Sequence < double > rLine = toPrint[i];
		double *line= rLine.getArray();
		for(int j=0;j<rLine.getLength();j++)
			cout << " " << line[j] << " ";
		cout << endl;
	}
}
 
double *SeqSeqToArray1D(const Sequence < Sequence < double> > &seqseq){
	sal_Int32 iMax=seqseq.getLength(),jMax;
	Sequence < double > rLine = seqseq[0];
	jMax=rLine.getLength();	
	double *table1D = new double[iMax*jMax];
	for (sal_Int32 i = 0 ; i < iMax; i++ )
		for(sal_Int32 j = 0 ; j < jMax; j++ )
			table1D[i*jMax+j]= seqseq[i][j];
	return table1D;
}

Using these sub is easy : it can be done like that :

//Listing 29 Using the conversion
//C+
// We first construct a sequence
	Sequence < double > demo(5);
	demo[0]=1.1;
    demo[1]=2.1;
	demo[2]=3.1;
	demo[3]=4.1;
	demo[4]=5.1;
// We then construct the sequence of sequence
	Sequence < Sequence < double > > seqseq(3);
	for (int i=0; i<seqseq.getLength();i++)
            seqseq[i]=demo;
// We print out the result of the construction	
	printOutSeqSeq(seqseq);
// Here is the conversion
	double *table = SeqSeqToArray1D(seqseq);
// We finish wit printing out the result 
	cout << "Array1D -> 2D : "<< endl;
	for (int i=0; i< 3; i++){
		for (int j=0;j<5;j++)
			cout<<" "<<table[i*5+j]<<" ";
		cout<<endl;
	}
	....
	delete table;

which gives us :

Prints out SeqSeq
 1.1  2.1  3.1  4.1  5.1
 1.1  2.1  3.1  4.1  5.1
 1.1  2.1  3.1  4.1  5.1
Array1D -> 2D :
 1.1  2.1  3.1  4.1  5.1
 1.1  2.1  3.1  4.1  5.1
 1.1  2.1  3.1  4.1  5.1
[smoutou@p3 Lifetime]$

Converting a sequence of sequence directly in an 2D array is not an easy task because the compiler has to know the size of the second index before compiling. At first something like

//Listing 30 Array2D conversion
// C++
double **SeqSeqToArray2D(const Sequence < Sequence < double> > &seqseq){
	double **table2D; 
	double *table1D;
	table1D = SeqSeqToArray1D(seqseq);
	table2D = &table1D;
	return table2D;
}

seems interesting but let's see if that works out. A first idea is to write something like :

//Listing 31 Wrong code for  conversion
// C++
	double **table2= SeqSeqToArray2D(seqseq);
	for (int i=0; i< 3; i++){
		for (int j=0;j<5;j++)
			cout<<" "<< table2[i][j]<<" ";
		cout<<endl;
	}
	delete table2;

but the compiler is unable to calculate table2[i][j] here. For that it has to evaluate the expression i*jMax+j but has no knowledge on jMax !!

More Abstractions with STL

If you plan to use C++ you will certainly use the STL extensively. We begin first by conversions. Here is the easier one :

//Listing 32 Converting a Sequence of Sequence into a vector
// C++
// Inspired by Eric Ehlers's code but using template
// See chapter 14
template< typename T>
vector < T >SeqSeqToVectorTemplate(const Sequence< Sequence < T > >& ss) {
    vector < T >v;
    for (int i=0; i<ss.getLength(); i++)
        for (int j=0; j<ss[i].getLength(); j++)
            v.push_back(ss[i][j]);
    return v;
}

My start point for achieving this code was Eric Ethler's code presented here. This code is again easy to use :

//Listing 33 Using the previous Convertion
// C++
#include <iostream>
#include<vector>
#include <cppuhelper/bootstrap.hxx>
#include <com/sun/star/uno/Sequence.hxx>
using namespace com::sun::star::uno;
using namespace std;
 
template< typename T>
vector < T >SeqSeqToVectorTemplate(const Sequence< Sequence < T > >& ss);
main( ) {
	Sequence < double > demo(5);
	demo[0]=1.1;
    demo[1]=2.1;
	demo[2]=3.1;
	demo[3]=4.1;
	demo[4]=5.1;
	Sequence < Sequence < double > > seqseq(3);
// simply use the same sequence
	for (int i=0; i<seqseq.getLength();i++)
            seqseq[i]=demo;
// template
	vector <double> v=SeqSeqToVectorTemplate(seqseq);
	cout << "vector1D -> 2D : "<< endl;
	for (int i=0; i< 3; i++){
		for (int j=0;j<5;j++)
			cout<<" "<<v[i*5+j]<<" ";
		cout<<endl;
	}
	return 0;
}

We give now three other conversions (see also here)

//Listing 34 Converting Utilities with Template
// C++
// Inspired by Eric Ethler's code but using template
// See chapter 14
template< typename T>
Sequence< Sequence< T > > VectorTemplateToSeqSeq(const vector < T > &v) {
    Sequence< Sequence< double > > ss(v.size());
    for (unsigned int i=0; i<v.size(); i++) {
        Sequence< T > s(1);
        s[0] = v[i];
        ss[i] = s;
    }
    return ss;
}
template< typename T>
vector < vector < T > >SeqSeqToMatrixTemplate(const Sequence< Sequence < T > >& ss) {
    vector < vector < T > >vv;
    for (int i=0; i<ss.getLength(); i++) {
        vector < T >v;
        for (int j=0; j<ss[i].getLength(); j++)
            v.push_back(ss[i][j]);
        vv.push_back(v);
    }
    return vv;
}
template< typename T>
Sequence< Sequence< T > > MatrixTemplateToSeqSeq(
			const std::vector < std::vector < T > >&vv) {
    Sequence< Sequence< T > > ss(vv.size());
    for (unsigned int i=0; i<vv.size(); i++) {
        std::vector < T > v = vv[i];
        Sequence< T > s(v.size());
        for (unsigned int j=0; j<v.size(); j++)
            s[j] = v[j];
        ss[i] = s;
    }
    return ss;
}

One way to use it is for instance :

//Listing 35 Converting Utilities with Template
//C++
	...
// seqseq must be initialized	
	vector <vector <double> > v2=SeqSeqToMatrixTemplate(seqseq);
	cout << "vector2D : "<< endl;
	for (int i=0; i< 3; i++){
		for (int j=0;j<5;j++)
			cout<<" "<<v2[i][j]<<" ";
		cout<<endl;
	}

Because there is a lot of algorithms based on STL I think these utilities will be very helpfull.


See also

Personal tools