Tutorial: "Hello World" with templates.
Code
Now we are going to create our first project that uses templates.
CppCMS template system consists of two important parts:
- The content that is rendered to HTML
- The template that can render given content to HTML
First we create content -- data.h:
#ifndef DATA_H
#define DATA_H
#include <cppcms/base_view.h>
#include <string>
namespace data {
struct message : public cppcms::base_content {
std::string message;
};
}
#endif
We create a content class "message" that must be
derived from cppcms::base_content class. It includes the data we want to show. In our case it is a simple string "message".
It is recommended to put all "content" classes to separate namespace.
Once the content is created we can create the template
that would render out content my_view.tmpl:
<% c++ #include "data.h" %>
<% namespace my_view %>
<% class message uses data::message %>
<% template render() %>
<html>
<body>
<h1><% message %> World!</h1>
</body>
<html>
<% end template %>
<% end class %>
<% end namespace %>
Every template directive enclosed by pair of <%, %>.
First line <% c++ ... %> represents any C++ code string. We need tell our class what content should be used. Thus we give an "include" for appropriate header.
Then we define namespace where all our templates are placed <% namespace my_view %> and then create a class that renders our content.
<% class message uses data::message %>
Class my_view::message would render data::message content. The primary function that should be implemented is "render()". After <% template render() %> we write the
body of our html message.
You can see <% message %> command. It tells that "message" member of our content class should be displayed.
Note: Every std::string automatically receives HTML escaping. Thus it is safe to show any row data there.
Now, lets see how we use it in our code.
First we call use_template("my_view") in the constructor of my_hello_world. It tells to application, which template set should be used for rendering.
Then, in main() function we write:
data::message c;
c.message=">>>Hello<<<";
render("message",c);
We create an instance of data::message --- "c". We set its message member with appropriate string we want to show. We may safely put any symbols like "<", they would be
automatically escaped.
Then we call render("message",c). It would use my_view::message class for rendering template content "c".
That's it, the code is complete.
Build
There are two options of building templates:
- Statically compile them into the executable
- Compile them as shared object and load them with application start-up.
Static build
First we compile our template
cppcms_tmpl_cc my_view.tmpl -o my_view.cpp
Then we can build our project
g++ hello.cpp my_view.cpp -lcppcms -o hello.fcgi
Now we run as usuall cppcms_run hello.fcgi -c conf.txt
Dynamic build is little bit more tricky.
After we had build our my_view.cpp we should compile it
as shared object:
g++ -shared -fPIC my_view.cpp -lcppcms -o my_view.so
Then compile our application with additional flag -export-dynamic.
g++ -export-dynamic hello.cpp -lcppcms -o hello.fcgi
Without this flag, RTTI, would not work between application and shared object and you may receive a error "incorrect content type".
Now we should let our application know where its templates are placed. We edit conf.txt and add following line:
templates.dirs={ "." }
When hello.fcgi starts, it would look in this directory
and try load all shared object it finds.
Now we can start our application as usual.
