示例#1
0
文件: emit_m.c 项目: cd127/lcm-1
static int emit_header(lcmgen_t *lcm, lcm_struct_t *ls)
{
	start_file("_new");

    // define the class
    emit(0, "function S = %s_new()", sn);
    emit(1,   "S = struct(...");

    // data members
	int const members = g_ptr_array_size(ls->members);

	for (unsigned int mx = 0; mx < members; mx++) {
		lcm_member_t *lm = (lcm_member_t *) g_ptr_array_index(ls->members, mx);
		char* lm_tnc = dots_to_double_colons(lm->type->lctypename);

		emit_start(2, "'%s', ", lm->membername);
		int const dimensions = g_ptr_array_size(lm->dimensions);
		int const primitive = lcm_is_primitive_type(lm->type->lctypename);
		if (0 == dimensions) {
			emit_continue("%s%s", map_type_name(lm_tnc) , primitive ? "(0)" : "_new()");
		} else {
			emit_continue("repmat( %s%s, [", map_type_name(lm_tnc), primitive ? "(0)" : "_new()");
			for (int dx = 0; dx < dimensions - 1; ++dx) {
				lcm_dimension_t *dim = (lcm_dimension_t *) g_ptr_array_index(lm->dimensions, dx);
				emit_continue("%s, ", dim->size);
			}
			lcm_dimension_t *dim = (lcm_dimension_t*) g_ptr_array_index(lm->dimensions, dimensions - 1);
			emit_continue("%s%s] )", dim->size, dimensions == 1 ? ", 1" : "");
		}
		emit_end("%s", (members == mx + 1 ? " );" : ",..."));
	}
	emit(0, "%%endfunction");
	emit(0, "");

//    // constants TODO
//    if (g_ptr_array_size(ls->constants) > 0) {
//        emit(1, "public:");
//        for (unsigned int i = 0; i < g_ptr_array_size(ls->constants); i++) {
//            lcm_constant_t *lc = (lcm_constant_t *) g_ptr_array_index(ls->constants, i);
//            assert(lcm_is_legal_const_type(lc->lctypename));
//
//            const char *suffix = "";
//            if (!strcmp(lc->lctypename, "int64_t"))
//              suffix = "LL";
//            char const * mapped_typename = map_type_name(lc->lctypename);
//            emit(2, "static const %-8s %s = %s%s;", mapped_typename,
//                lc->membername, lc->val_str, suffix);
//            //free(mapped_typename);
//        }
//        emit(0, "");
//    }
//	emit(9, "};");
//
//    free(tn_);
	end_file();
}
示例#2
0
文件: emit_m.c 项目: cd127/lcm-1
static int emit_encoded_size_nohash(lcmgen_t *lcm, lcm_struct_t *ls)
{
	start_file("_encodedSize_nohash");

    emit(0, "function s = %s_encodedSize_nohash(S)", sn);
    emit(1,   "s = uint32(0);");
    for (unsigned int m = 0; m < g_ptr_array_size(ls->members); m++) {
        lcm_member_t *lm = (lcm_member_t *) g_ptr_array_index(ls->members, m);
		char* lm_tnc = dots_to_double_colons(lm->type->lctypename);

		int const encsize = encoded_size(lm_tnc);
		int const dimensions = g_ptr_array_size(lm->dimensions);

		if (encsize > -1) {//known constant size
			emit_start(1, "s = s + %d", encsize);
			for (int dx = 0; dx < dimensions; ++dx) {
				lcm_dimension_t *dim = (lcm_dimension_t*) g_ptr_array_index(lm->dimensions, dx);
				emit_continue(" * %s", dim->size);
			}
			emit_end(";");
		}
		else {
			if (0 == dimensions) {
				emit(1, "s = s + %s_encodedSize_nohash(S.%s);", map_type_name(lm_tnc), lm->membername);
			}
			else {
				//emit: for each dimension
				for (int dx = 0; dx < dimensions; ++dx) {
					lcm_dimension_t *dim = (lcm_dimension_t*) g_ptr_array_index(lm->dimensions, dx);
					emit(1 + dx, "for dx%d = 1:%s", dx, dim->size);
				}

				{//do
					emit_start(1 + dimensions, "s = s + %s_encodedSize_nohash(S.%s(", map_type_name(lm_tnc), lm->membername);
					for (int dx = 0; dx < dimensions - 1; ++dx) {
						emit_continue("dx%d,", dx);
					}
					emit_end("dx%d));", dimensions - 1);
				}

				//end
				for (int dx = dimensions; dx > 0; --dx) {
					emit(dx, "end");
				}
			}
		}
	
		free(lm_tnc);
	}
    emit(0, "%%endfunction");
    emit(0, "");

	end_file();
}
示例#3
0
文件: emit_c.c 项目: tbeu/lcm
static void emit_c_array_loops_start(lcmgen_t *lcm, FILE *f, lcm_member_t *lm, const char *n, int flags)
{
    if (g_ptr_array_size(lm->dimensions) == 0)
        return;

    for (unsigned int i = 0; i < g_ptr_array_size(lm->dimensions) - 1; i++) {
        char var = 'a' + i;

        if (flags & FLAG_EMIT_MALLOCS) {
            char stars[1000];
            for (unsigned int s = 0; s < g_ptr_array_size(lm->dimensions) - 1 - i; s++) {
                stars[s] = '*';
                stars[s+1] = 0;
            }

            emit(2+i, "%s = (%s%s*) lcm_malloc(sizeof(%s%s) * %s);",
                 make_accessor(lm, n, i),
                 map_type_name(lm->type->lctypename),
                 stars,
                 map_type_name(lm->type->lctypename),
                 stars,
                 make_array_size(lm, n, i));
        }

        emit(2+i, "{ int %c;", var);
        emit(2+i, "for (%c = 0; %c < %s; %c++) {", var, var, make_array_size(lm, "p", i), var);
    }

    if (flags & FLAG_EMIT_MALLOCS) {
        emit(2 + g_ptr_array_size(lm->dimensions) - 1, "%s = (%s*) lcm_malloc(sizeof(%s) * %s);",
             make_accessor(lm, n, g_ptr_array_size(lm->dimensions) - 1),
             map_type_name(lm->type->lctypename),
             map_type_name(lm->type->lctypename),
             make_array_size(lm, n, g_ptr_array_size(lm->dimensions) - 1));
    }
}
示例#4
0
文件: emit_m.c 项目: cd127/lcm-1
static int emit_decode_nohash(lcmgen_t *lcm, lcm_struct_t *ls)
{
	start_file("_decode_nohash");

    emit(0, "function [pos, S] = %s_decode_nohash(buf, pos, maxlen, S, elems)", sn);
	emit(1,   "for ix = 1:elems");
    for (unsigned int m = 0; m < g_ptr_array_size(ls->members); m++) {
        lcm_member_t *lm = (lcm_member_t *) g_ptr_array_index(ls->members, m);
		char* lm_tnc = dots_to_double_colons(lm->type->lctypename);

		int const dimensions = g_ptr_array_size(lm->dimensions);
		if (0 == dimensions) {
			emit(2, "[pos, t] = %s_decode_nohash(buf, pos, maxlen, S(ix).%s, 1);", map_type_name(lm_tnc), lm->membername);
			emit(2, "S(ix).%s = t(1);", lm->membername);
		}
		else {
			//emit: for each dimension
			for (int dx = 0; dx < dimensions - 1; ++dx) {
				lcm_dimension_t *dim = (lcm_dimension_t*) g_ptr_array_index(lm->dimensions, dx);
				emit(2 + dx, "for dx%d = 1:%s", dx, dim->size);
			}

			{//do
				emit_start(1 + (dimensions > 1 ? dimensions : 1), "[pos, t] = %s_decode_nohash(buf, pos, maxlen, S(ix).%s(", map_type_name(lm_tnc), lm->membername);
				for (int dx = 0; dx < dimensions - 1; ++dx) {
					emit_continue("dx%d,", dx);
				}
				lcm_dimension_t *dim = (lcm_dimension_t*) g_ptr_array_index(lm->dimensions, dimensions - 1);
				emit_end(":), %s);", dim->size);

				emit_start(1 + (dimensions > 1 ? dimensions : 1), "S(ix).%s(", lm->membername);
				for (int dx = 0; dx < dimensions - 1; ++dx) {
					emit_continue("dx%d,", dx);
				}
				emit_end(":) = t(1:%s);", dim->size);
			}

			//end
			for (int dx = dimensions - 1; dx > 0; --dx) {
				emit(1 + dx, "end");
			}
		}
		free(lm_tnc);
	}
    emit(1,   "end");
    emit(0, "%%endfunction");
	end_file();
}
示例#5
0
文件: emit_cpp.c 项目: cd127/lcm-1
static void emit_init_test(lcmgen_t *lcm, FILE *f, lcm_struct_t *ls)
{
    const char *sn = ls->structname->shortname;
    emit(0, "bool %s::initTestObject()", sn);
    emit(0, "{");
    if(0 == g_ptr_array_size(ls->members)) {
        emit(1,     "return true;");
        emit(0,"}");
        emit(0,"");
        return;
    }
    // For each member
    for (unsigned int mInd = 0; mInd < g_ptr_array_size(ls->members); mInd++) {
        lcm_member_t *lm = (lcm_member_t *) g_ptr_array_index(ls->members, mInd);
        char const* mapped_typename = map_type_name(lm->type->lctypename);
        char const* typeInitValue = init_test_value(mapped_typename);
        char * valueAssignment;

        // For non-primitive types, simply call object's init function
        if ( ! lcm_is_primitive_type(lm->type->lctypename) ) {
            valueAssignment = strdup(".initTestObject();");
        }
        else {
            valueAssignment = g_strdup_printf(" = %s;", typeInitValue);
        }

        int ndim = g_ptr_array_size(lm->dimensions);

        if (0==ndim) {
            emit(1, "%s%s", lm->membername, valueAssignment);
            free (valueAssignment);
        }
        else {
            // Check if it's a dynamic array, in which case we ignore it at the moment.
            uint8_t isDynamic=0;
            for (int dim=0; dim < ndim; ++dim) {
                lcm_dimension_t *ld = (lcm_dimension_t *) g_ptr_array_index(lm->dimensions, dim);
                if (!is_dim_size_fixed(ld->size)) {
                    isDynamic=1;
                    break;
                }
            }
            if (!isDynamic) {
                // Set first component in array
                emit_start(1, "%s", lm->membername);
                for (int dim=0; dim < ndim; ++dim) {
                    emit_continue("[0]");
                }
                emit_end("%s", valueAssignment);

                // Set last component in array
                emit_start(1, "%s", lm->membername);
                for (int dim=0; dim < ndim; ++dim) {
                    lcm_dimension_t *ld = (lcm_dimension_t *) g_ptr_array_index(lm->dimensions, dim);
                    emit_continue("[%i]", atoi(ld->size)-1);
                }
                emit_end("%s", valueAssignment);
            }
            else {
                emit(1, "//%s is a dynamic array", lm->membername);
            }
            g_free (valueAssignment);
            free((char*)mapped_typename);
            free((char*)typeInitValue);
        }
    }
    emit(0, "");
    emit(1, "return true;");
    emit(0,"}");
    emit(0,"");
}
示例#6
0
文件: emit_cpp.c 项目: cd127/lcm-1
/** Emit header file **/
static void emit_header_start(lcmgen_t *lcmgen, FILE *f, lcm_struct_t *ls)
{
    char *tn = ls->structname->lctypename;
    char *sn = ls->structname->shortname;
    char *tn_ = dots_to_underscores(tn);

    emit_auto_generated_warning(f);

    fprintf(f, "#include <lcm/lcm_coretypes.h>\n");
    fprintf(f, "\n");
    fprintf(f, "#ifndef __%s_hpp__\n", tn_);
    fprintf(f, "#define __%s_hpp__\n", tn_);
    fprintf(f, "\n");

    // do we need to #include <vector> ?
    int emit_include_vector = 0;
    for (unsigned int mind = 0; mind < g_ptr_array_size(ls->members); mind++) {
        lcm_member_t *lm = (lcm_member_t *)g_ptr_array_index(ls->members, mind);
        if (g_ptr_array_size(lm->dimensions) != 0 &&
                !lcm_is_constant_size_array(lm) && !emit_include_vector) {
            emit(0, "#include <vector>");
            emit_include_vector = 1;
        }
    }

    emit(0, "#include <cmath>\t// For fabs to compare floats");
    emit(0, "#include <string>\t// For return type of toStr()");
    emit(0, "#include <sstream>\t// For stringstream in toStr()");

    // include header files for other LCM types
    for (unsigned int mind = 0; mind < g_ptr_array_size(ls->members); mind++) {
        lcm_member_t *lm = (lcm_member_t *) g_ptr_array_index(ls->members, mind);

        if (!lcm_is_primitive_type(lm->type->lctypename) &&
                strcmp(lm->type->lctypename, ls->structname->lctypename)) {
            char *other_tn = dots_to_slashes (lm->type->lctypename);
            emit(0, "#include \"%s%s%s.hpp\"",
                 getopt_get_string(lcmgen->gopt, "cpp-include"),
                 strlen(getopt_get_string(lcmgen->gopt, "cpp-include"))>0 ? G_DIR_SEPARATOR_S : "",
                 other_tn);
            free(other_tn);
        }
    }

    fprintf(f, "\n");
    emit_package_namespace_start(lcmgen, f, ls);

    // define the class
    emit(0, "");
    emit_comment(f, 0, ls->comment);
    emit(0, "class %s", sn);
    emit(0, "{");

    // data members
    if(g_ptr_array_size(ls->members)) {
        emit(1, "public:");
        for (unsigned int mind = 0; mind < g_ptr_array_size(ls->members); mind++) {
            lcm_member_t *lm = (lcm_member_t *) g_ptr_array_index(ls->members, mind);

            emit_comment(f, 2, lm->comment);
            char const* mapped_typename = map_type_name(lm->type->lctypename);
            int ndim = g_ptr_array_size(lm->dimensions);
            if (ndim == 0) {
                emit(2, "%-10s %s;", mapped_typename, lm->membername);
            } else {
                if (lcm_is_constant_size_array(lm)) {
                    emit_start(2, "%-10s %s", mapped_typename, lm->membername);
                    for (unsigned int d = 0; d < ndim; d++) {
                        lcm_dimension_t *ld = (lcm_dimension_t *) g_ptr_array_index(lm->dimensions, d);
                        emit_continue("[%s]", ld->size);
                    }
                    emit_end(";");
                } else {
                    emit_start(2, "");
                    for (unsigned int d = 0; d < ndim; d++)
                        emit_continue("std::vector< ");
                    emit_continue("%s", mapped_typename);
                    for (unsigned int d = 0; d < ndim; d++)
                        emit_continue(" >");
                    emit_end(" %s;", lm->membername);
                }
            }
            if (mind < g_ptr_array_size(ls->members) - 1) {
                emit(0, "");
            }
        }
        emit(0, "");
    }

    // constants
    if (g_ptr_array_size(ls->constants) > 0) {
        emit(1, "public:");
        for (unsigned int i = 0; i < g_ptr_array_size(ls->constants); i++) {
            lcm_constant_t *lc = (lcm_constant_t *) g_ptr_array_index(ls->constants, i);
            assert(lcm_is_legal_const_type(lc->lctypename));

            emit_comment(f, 2, lc->comment);
            // For int32_t only, we emit enums instead of static const
            // values because the former can be passed by reference while
            // the latter cannot.
            if (!strcmp(lc->lctypename, "int32_t")) {
                emit(2, "enum { %s = %s };", lc->membername, lc->val_str);
            } else {
                const char *suffix = "";
                if (!strcmp(lc->lctypename, "int64_t"))
                    suffix = "LL";
                char const* mapped_typename = map_type_name(lc->lctypename);
                char *cpp_std = getopt_get_string(lcmgen->gopt, "cpp-std");
                if(strcmp("c++98",cpp_std) && strcmp("c++11",cpp_std)) {
                    printf("%s is not a valid cpp_std. Use --cpp-std=c++98 or --cpp-std=c++11 instead\n\n", cpp_std);
                    fflush(stdout);
                    _exit(1);
                }

                if(!strcmp (cpp_std, "c++11")) {
                    emit(2, "static constexpr %-8s %s = %s%s;", mapped_typename,
                         lc->membername, lc->val_str, suffix);
                } else {
                    emit(2, "// If you're using C++11 and are getting compiler errors saying things like");
                    emit(2, "// ‘constexpr’ needed for in-class initialization of static data member");
                    emit(2, "// then re-run lcm-gen with '--cpp-std=c++11' to generate code that is");
                    emit(2, "// compliant with C++11");
                    emit(2, "static const %-8s %s = %s%s;", mapped_typename,
                         lc->membername, lc->val_str, suffix);
                }
            }
        }
        emit(0, "");
    }

    emit(1, "public:");
    emit(2, "/**");
    emit(2, " * Encode a message into binary form.");
    emit(2, " *");
    emit(2, " * @param buf The output buffer.");
    emit(2, " * @param offset Encoding starts at thie byte offset into @p buf.");
    emit(2, " * @param maxlen Maximum number of bytes to write.  This should generally be");
    emit(2, " *  equal to getEncodedSize().");
    emit(2, " * @return The number of bytes encoded, or <0 on error.");
    emit(2, " */");
    emit(2, "inline int encode(void *buf, int offset, int maxlen) const;");
    emit(0, "");
    emit(2, "/**");
    emit(2, " * Check how many bytes are required to encode this message.");
    emit(2, " */");
    emit(2, "inline int getEncodedSize() const;");
    emit(0, "");
    emit(2, "/**");
    emit(2, " * Decode a message from binary form into this instance.");
    emit(2, " *");
    emit(2, " * @param buf The buffer containing the encoded message.");
    emit(2, " * @param offset The byte offset into @p buf where the encoded message starts.");
    emit(2, " * @param maxlen The maximum number of bytes to reqad while decoding.");
    emit(2, " * @return The number of bytes decoded, or <0 if an error occured.");
    emit(2, " */");
    emit(2, "inline int decode(const void *buf, int offset, int maxlen);");
    emit(0, "");
    emit(2, "/**");
    emit(2, " * Compare two instances of the same type.");
    emit(2, " *");
    emit(2, " * @param[in] other The object to compare.");
    emit(2, " * @return true if all elements are equal, false otherwise.");
    emit(2, " */");
    emit(2, "inline bool operator==(%s const & other) const;", sn);
    emit(0, "");
    emit(2, "/**");
    emit(2, " * Construct a string from the object for debugging purposes.");
    emit(2, " * Note that arrays are cropped for readability. Only the first and last elements are shown.");
    emit(2, " *");
    emit(2, " * @param[in] layout A placeholder for the tree structure.");
    emit(2, " */");
    emit(2, "inline std::string toDebugStr(std::string const & layout=\"|-\") const;");
    emit(0, "");
    emit(2, "/**");
    emit(2, " * Initialize all values of a test object to pre-defined values.");
    emit(2, " * The values used are much more informative than using 0 because");
    emit(2, " * they are type-dependant. This way, the user knows directly whether");
    emit(2, " * the type is correct or not. Typically the default values are the");
    emit(2, " * maximum value allowed by the type minus 5, and 1.0 for float and double.");
    emit(2, " * Note that for arrays only the first and last elements are considered.");
    emit(2, " *");
    emit(2, " * @return success.");
    emit(2, " */");
    emit(2, "inline bool initTestObject();");
    emit(0, "");
    emit(2, "/**");
    emit(2, " * Increment every variable in the object.");
    emit(2, " * Works well with initTestObject() and compareTestObject().");
    emit(2, " * Note that for arrays only the first and last elements are considered.");
    emit(2, " *");
    emit(2, " * @return success.");
    emit(2, " */");
    emit(2, "inline bool incTestObject();");
    emit(0, "");
    emit(2, "/**");
    emit(2, " * Compare two instances of the same type.");
    emit(2, " * Works well with initTestObject() and incTestObject().");
    emit(2, " * Note that for arrays only the first and last elements are considered.");
    emit(2, " *");
    emit(2, " * @param[in] other The object to compare.");
    emit(2, " * @return true if all elements are equal, false otherwise.");
    emit(2, " */");
    emit(2, "inline bool compareTestObject(%s const & other) const;", sn);
    emit(0, "");
    emit(2, "/**");
    emit(2, " * Retrieve the 64-bit fingerprint identifying the structure of the message.");
    emit(2, " * Note that the fingerprint is the same for all instances of the same");
    emit(2, " * message type, and is a fingerprint on the message type definition, not on");
    emit(2, " * the message contents.");
    emit(2, " */");
    emit(2, "inline static int64_t getHash();");
    emit(0, "");
    emit(2, "/**");
    emit(2, " * Returns \"%s\"", ls->structname->shortname);
    emit(2, " */");
    emit(2, "inline static const char* getTypeName();");

    emit(0, "");
    emit(2, "// LCM support functions. Users should not call these");
    emit(2, "inline int _encodeNoHash(void *buf, int offset, int maxlen) const;");
    emit(2, "inline int _getEncodedSizeNoHash() const;");
    emit(2, "inline int _decodeNoHash(const void *buf, int offset, int maxlen);");
    emit(2, "inline static uint64_t _computeHash(const __lcm_hash_ptr *p);");
    emit(0, "};");
    emit(0, "");

    free(tn_);
}
示例#7
0
文件: emit_c.c 项目: tbeu/lcm
/** Emit header file output specific to a particular type of struct. **/
static void emit_header_struct(lcmgen_t *lcm, FILE *f, lcm_struct_t *ls)
{
    char *tn = ls->structname->lctypename;
    char *tn_ = dots_to_underscores(tn);
    char *tn_upper = g_utf8_strup(tn_, -1);

    // include header files required by members
    for (unsigned int i = 0; i < g_ptr_array_size(ls->members); i++) {
        lcm_member_t *lm = (lcm_member_t *) g_ptr_array_index(ls->members, i);

        if (!lcm_is_primitive_type(lm->type->lctypename) &&
             strcmp(lm->type->lctypename, ls->structname->lctypename)) {
            char *other_tn = dots_to_underscores (lm->type->lctypename);
            fprintf(f, "#include \"%s%s%s.h\"\n",
                    getopt_get_string(lcm->gopt, "cinclude"),
                    strlen(getopt_get_string(lcm->gopt, "cinclude"))>0 ? "/" : "",
                    other_tn);
            free (other_tn);
        }
    }

    // output constants
    for (unsigned int i = 0; i < g_ptr_array_size(ls->constants); i++) {
        lcm_constant_t *lc = (lcm_constant_t *) g_ptr_array_index(ls->constants, i);
        assert(lcm_is_legal_const_type(lc->lctypename));
        const char *suffix = "";
        if (!strcmp(lc->lctypename, "int64_t")) {
            suffix = "LL";
        }
        emit_comment(f, 0, lc->comment);
        emit(0, "#define %s_%s %s%s", tn_upper, lc->membername, lc->val_str,
                suffix);
    }
    if (g_ptr_array_size(ls->constants) > 0) {
        emit(0, "");
    }

    // define the struct
    emit_comment(f, 0, ls->comment);
    emit(0, "typedef struct _%s %s;", tn_, tn_);
    emit(0, "struct _%s", tn_);
    emit(0, "{");

    for (unsigned int m = 0; m < g_ptr_array_size(ls->members); m++) {
        lcm_member_t *lm = (lcm_member_t *) g_ptr_array_index(ls->members, m);

        emit_comment(f, 1, lm->comment);

        int ndim = g_ptr_array_size(lm->dimensions);
        if (ndim == 0) {
            emit(1, "%-10s %s;", map_type_name(lm->type->lctypename),
                    lm->membername);
        } else {
            if (lcm_is_constant_size_array(lm)) {
                emit_start(1, "%-10s %s", map_type_name(lm->type->lctypename), lm->membername);
                for (unsigned int d = 0; d < ndim; d++) {
                    lcm_dimension_t *ld = (lcm_dimension_t *) g_ptr_array_index(lm->dimensions, d);
                    emit_continue("[%s]", ld->size);
                }
                emit_end(";");
            } else {
                emit_start(1, "%-10s ", map_type_name(lm->type->lctypename));
                for (unsigned int d = 0; d < ndim; d++)
                    emit_continue("*");
                emit_end("%s;", lm->membername);
            }
        }
    }
    emit(0, "};");
    emit(0, "");

    free(tn_);
    g_free(tn_upper);
}
示例#8
0
文件: emit_cpp.c 项目: ahans/lcm
/** Emit header file **/
static void emit_header_start(lcmgen_t *lcmgen, FILE *f, lcm_struct_t *ls)
{
    char *tn = ls->structname->lctypename;
    char *sn = ls->structname->shortname;
    char *tn_ = dots_to_underscores(tn);

    emit_auto_generated_warning(f);

    fprintf(f, "#include <lcm/lcm_coretypes.h>\n");
    fprintf(f, "\n");
    fprintf(f, "#ifndef __%s_hpp__\n", tn_);
    fprintf(f, "#define __%s_hpp__\n", tn_);
    fprintf(f, "\n");

    // do we need to #include <vector> and/or <string>?
    int emit_include_vector = 0;
    int emit_include_string = 0;
    for (unsigned int mind = 0; mind < g_ptr_array_size(ls->members); mind++) {
        lcm_member_t *lm = (lcm_member_t *)g_ptr_array_index(ls->members, mind);
        if (g_ptr_array_size(lm->dimensions) != 0 &&
            !lcm_is_constant_size_array(lm) && !emit_include_vector) {
            emit(0, "#include <vector>");
            emit_include_vector = 1;
        }
        if(!emit_include_string &&
            !strcmp(lm->type->lctypename, "string")) {
            emit(0, "#include <string>");
            emit_include_string = 1;
        }
    }

    // include header files for other LCM types
    for (unsigned int mind = 0; mind < g_ptr_array_size(ls->members); mind++) {
        lcm_member_t *lm = (lcm_member_t *) g_ptr_array_index(ls->members, mind);

        if (!lcm_is_primitive_type(lm->type->lctypename) &&
            strcmp(lm->type->lctypename, ls->structname->lctypename)) {
            char *other_tn = dots_to_slashes (lm->type->lctypename);
            emit(0, "#include \"%s%s%s.hpp\"",
                    getopt_get_string(lcmgen->gopt, "cpp-include"),
                    strlen(getopt_get_string(lcmgen->gopt, "cpp-include"))>0 ? G_DIR_SEPARATOR_S : "",
                    other_tn);
            free(other_tn);
        }
    }

    fprintf(f, "\n");
    emit_package_namespace_start(lcmgen, f, ls);

    // define the class
    emit(0, "");
    emit_comment(f, 0, ls->comment);
    emit(0, "class %s", sn);
    emit(0, "{");

    // data members
    if(g_ptr_array_size(ls->members)) {
        emit(1, "public:");
        for (unsigned int mind = 0; mind < g_ptr_array_size(ls->members); mind++) {
            lcm_member_t *lm = (lcm_member_t *) g_ptr_array_index(ls->members, mind);

            emit_comment(f, 2, lm->comment);
            char* mapped_typename = map_type_name(lm->type->lctypename);
            int ndim = g_ptr_array_size(lm->dimensions);
            if (ndim == 0) {
                emit(2, "%-10s %s;", mapped_typename, lm->membername);
            } else {
                if (lcm_is_constant_size_array(lm)) {
                    emit_start(2, "%-10s %s", mapped_typename, lm->membername);
                    for (unsigned int d = 0; d < ndim; d++) {
                        lcm_dimension_t *ld = (lcm_dimension_t *) g_ptr_array_index(lm->dimensions, d);
                        emit_continue("[%s]", ld->size);
                    }
                    emit_end(";");
                } else {
                    emit_start(2, "");
                    for (unsigned int d = 0; d < ndim; d++)
                        emit_continue("std::vector< ");
                    emit_continue("%s", mapped_typename);
                    for (unsigned int d = 0; d < ndim; d++)
                        emit_continue(" >");
                    emit_end(" %s;", lm->membername);
                }
            }
            free(mapped_typename);
            if (mind < g_ptr_array_size(ls->members) - 1) {
                emit(0, "");
            }
        }
        emit(0, "");
    }

    // constants
    if (g_ptr_array_size(ls->constants) > 0) {
        emit(1, "public:");
        for (unsigned int i = 0; i < g_ptr_array_size(ls->constants); i++) {
            lcm_constant_t *lc = (lcm_constant_t *) g_ptr_array_index(ls->constants, i);
            assert(lcm_is_legal_const_type(lc->lctypename));

            emit_comment(f, 2, lc->comment);
            // For int32_t only, we emit enums instead of static const
            // values because the former can be passed by reference while
            // the latter cannot.
            if (!strcmp(lc->lctypename, "int32_t")) {
              emit(2, "enum { %s = %s };", lc->membername, lc->val_str);
            } else {
              const char *suffix = "";
              if (!strcmp(lc->lctypename, "int64_t"))
                suffix = "LL";
              char* mapped_typename = map_type_name(lc->lctypename);
              emit(2, "static const %-8s %s = %s%s;", mapped_typename,
                  lc->membername, lc->val_str, suffix);
              free(mapped_typename);
            }
        }
        emit(0, "");
    }

    emit(1, "public:");
    emit(2, "/**");
    emit(2, " * Encode a message into binary form.");
    emit(2, " *");
    emit(2, " * @param buf The output buffer.");
    emit(2, " * @param offset Encoding starts at thie byte offset into @p buf.");
    emit(2, " * @param maxlen Maximum number of bytes to write.  This should generally be");
    emit(2, " *  equal to getEncodedSize().");
    emit(2, " * @return The number of bytes encoded, or <0 on error.");
    emit(2, " */");
    emit(2, "inline int encode(void *buf, int offset, int maxlen) const;");
    emit(0, "");
    emit(2, "/**");
    emit(2, " * Check how many bytes are required to encode this message.");
    emit(2, " */");
    emit(2, "inline int getEncodedSize() const;");
    emit(0, "");
    emit(2, "/**");
    emit(2, " * Decode a message from binary form into this instance.");
    emit(2, " *");
    emit(2, " * @param buf The buffer containing the encoded message.");
    emit(2, " * @param offset The byte offset into @p buf where the encoded message starts.");
    emit(2, " * @param maxlen The maximum number of bytes to reqad while decoding.");
    emit(2, " * @return The number of bytes decoded, or <0 if an error occured.");
    emit(2, " */");
    emit(2, "inline int decode(const void *buf, int offset, int maxlen);");
    emit(0, "");
    emit(2, "/**");
    emit(2, " * Retrieve the 64-bit fingerprint identifying the structure of the message.");
    emit(2, " * Note that the fingerprint is the same for all instances of the same");
    emit(2, " * message type, and is a fingerprint on the message type definition, not on");
    emit(2, " * the message contents.");
    emit(2, " */");
    emit(2, "inline static int64_t getHash();");
    emit(0, "");
    emit(2, "/**");
    emit(2, " * Returns \"%s\"", ls->structname->shortname);
    emit(2, " */");
    emit(2, "inline static const char* getTypeName();");

    emit(0, "");
    emit(2, "// LCM support functions. Users should not call these");
    emit(2, "inline int _encodeNoHash(void *buf, int offset, int maxlen) const;");
    emit(2, "inline int _getEncodedSizeNoHash() const;");
    emit(2, "inline int _decodeNoHash(const void *buf, int offset, int maxlen);");
    emit(2, "inline static int64_t _computeHash(const __lcm_hash_ptr *p);");
    emit(0, "};");
    emit(0, "");

    free(tn_);
}