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.