This tutorial will guide you through the creation of various example C++ applications, highlighting important Chromium C++ concepts. This tutorial assumes robust knowledge of C++ (the language) but does not assume you know how to write an application specific to Chromium‘s style and architecture. This tutorial does assume that you know how to check files out of Chromium‘s repository.
As always, consider the following resources as of primary importance:
This tutorial does not assume you have read any of the above, though you should feel free to peruse them when necessary. This tutorial will cover information across all of those guides. Exercise 0: "Hello World!"This exercise demonstrates the use of the ninja build system to build a simple C++ binary and demonstrates how typical C++ builds are organized within Chromium. Create a new target in Sample execution: $ cd /path/to/chromium/src $ gclient runhooks
$ ninja -C out/Default hello_world $ out/Default/hello_world Hello, world! AMI: might be confusing how rietveld shows the new file as a copy/diff against an unrelated file.
AMI: output doesn‘t actually match what‘s in the solution. Might be confusing.
Part 1: Using command-line argumentsWe will augment our int main(int argc, char** argv) { CommandLine::Init(argc, argv); // Main program execution ... return 0; } Flags are not explicitly defined in Chromium. Instead, we use GetSwitchValueAsASCII() and friends to retrieve values passed in.Important include files#include "base/command_line.h" Exercise 1: Using command-line argumentsChange Part 2: Callbacks and BindC++, unlike other languages such as Python, Javascript, or Lisp, has only rudimentary support for callbacks and no support for partial application. However, Chromium has the AMI: last sentence might benefit from a pointer to refcounting (without which it might be less clear how binding works with copying of bound closures). The // The type of a callback that: // - Can run only once. / / - Is move-only and non-copyable./ / - Takes no arguments and does not return anything.// base::OnceClosure is an alias of this type. base::OnceCallback<void()>
// The types of a callback that takes two arguments (a string and a double) // and returns an int. base::OnceCallback<int(std::string, double)> base::RepeatingCallback<int(std::string, double)> Callbacks are executed by invoking the void MyFunction1(base::OnceCallback<int(std::string, double)> my_callback) { // OnceCallback
... }
int result1 = my_callback.Run("my string 1", 1.0);
// Run() can be called as many times as you wish for RepeatingCallback. int result2 = my_callback.Run("my string 2", 2); ... } Callbacks are constructed using the // Declare a function. void MyFunction(int32 a, double b); base::OnceCallback<void(double)> my_callback1 = base::BindOnce(&MyFunction, 10); base::RepeatingCallback<void(double)> my_callback2 = base::BindRepeating(&MyFunction, 10); // Equivalent to: // // MyFunction(10, 3.5); // std::move(my_callback1).Run(3.5); my_callback2.Run(3.5);
Important Include FilesExercise 2: Fibonacci closuresImplement a function that returns a callback that takes no arguments and returns successive Fibonacci numbers. That is, a function that can be used like this: base::RepeatingCallback<int()> fibonacci_closure = MakeFibonacciClosure(); printf("%d\n", fibonacci_closure.Run()); // Prints "1" printf("%d\n", fibonacci_closure.Run()); // Prints "1" printf("%d\n", fibonacci_closure.Run()); // Prints "2" ... Each returned Fibonacci callback should be independent; running one callback shouldn‘t affect the result of running another callback. Write a fibonacci executable that takes an integer argument n and uses your function to print out the first n Fibonacci numbers.(This exercise was inspired by this Go exercise: Function closures.) Exercise solution Part 3: Message loopsChromium‘s abstraction for event loops is
base::MessageLoop . base::MessageLoop handles running tasks (which are instances of base::Closure ) on the current thread. Given a pointer to the message loop for a thread, you can post tasks on it with base::MessageLoop::PostTask (or base::MessageLoop::PostDelayedTask if you want to add a delay).Normally you wouldn‘t have to worry about setting up a
base::MessageLoop and keeping it running, since that is automatically done by Chromium‘s thread classes. However, since the main thread doesn‘t automatically start off with a base::MessageLoop , you have to create, pump, and shutdown one yourself if you‘re writing a new executable. The base::RunLoop class is the current recommended way of doing that.#include "base/message_loop/message_loop.h" Exercise 3: SleepImplement the Unix command-line utility Part 4: Threads and task runnersChromium‘s platform-independent abstraction for threads is Chromium‘s abstraction for asynchronously running posted tasks is An important member function of Important header files#include "base/task_runner.h" More informationExercise 4: Integer factorizationTake the given (slow) function to find a non-trivial factor of a given integer: bool FindNonTrivialFactor(int n, int* factor) { // Really naive algorithm. for (int i = n-1; i >= 2; --i) { if (n % i == 0) { *factor = i; return true; } } return false; }Write a command-line utility |