OleksandrKvl / sbepp

C++ implementation of the FIX Simple Binary Encoding
https://oleksandrkvl.github.io/sbepp/
MIT License
40 stars 4 forks source link

help folllowing the example and getting my own simple test working #65

Closed timbo100 closed 4 weeks ago

timbo100 commented 1 month ago

@OleksandrKvl

I've been trying to put an example together that uses my simple case, but the examples have gaps in explanation, IMO and I would appreciate your help.

I'm following very carefully the example

within one program I'm trying to use my message scheme (3 fields) to encode into buffer and then decode from address and size generated.

============= my Schema ============= My message schema: file: timesmsg1.xml

<?xml version="1.0" encoding="UTF-8"?>
<sbe:messageSchema xmlns:sbe="http://fixprotocol.io/2016/sbe"
                   xmlns:xi="http://www.w3.org/2001/XInclude"
                   package="three_arg_msg1"
                   id="1"
                   version="0"
                   semanticVersion="5.2"
                   description="Schema to test endianness"
                   byteOrder="bigEndian">
    <types>
        <composite name="messageHeader">
            <type name="blockLength" primitiveType="uint16"/>
            <type name="templateId" primitiveType="uint16"/>
            <type name="schemaId" primitiveType="uint16"/>
            <type name="version" primitiveType="uint16"/>
        </composite>

        <composite name="composite_19">
            <type name="float_field" primitiveType="float"/>
        </composite>

        <composite name="varStrEncoding">
            <type name="length" primitiveType="uint32"/>
            <type name="varData" primitiveType="char" length="0"/>
        </composite>
    </types>

    <sbe:message name="msg1" id="1">
        <data name="date" id="1" type="varStrEncoding"/>
        <data name="time" id="2" type="varStrEncoding"/>
        <data name="meno" id="3" type="varStrEncoding"/>
    </sbe:message>
</sbe:messageSchema>

============= my generated files ============= that were copied into my project three_arg_msg1.zip

============= my test program ============= My message schema: file: msg1.xml

#include "stdio.h"
#include <iostream>

#include "three_arg_msg1/messages/msg1.hpp"   // copied over from sbeppc generation

int main() {
    std::array<char, 1024> buf{};

    auto m = sbepp::make_view<three_arg_msg1::detail::messages::message_1>(buf.data(), buf.size());
    sbepp::fill_message_header(m);

    auto d = m.date();
    d.assign_string("2/23/2010");

    auto t = m.time();
    t.assign_string("12:13:123");

    auto c = m.meno();
    c.assign_string("33333.234");
    // 
    const auto msg_size = sbepp::size_bytes(m);
    char* addr = sbepp::addressof(m) ;
    printf(" msg_size=%ld, address of m = %lld\n", msg_size, (unsigned long long)addr) ;
    /// =============== Now Decode (as if received over network comm ====================
    auto header = sbepp::make_const_view<sbepp::schema_traits<three_arg_msg1::schema>::header_type>(addr, msg_size);

    if(*header.templateId() != sbepp::message_traits<three_arg_msg1::schema::messages::msg1>::id()) {
        std::cout << "unknown message id: " << *header.templateId() << '\n'; 
        exit(1);
    } else {
        printf("header id OK!!\n") ;
    }
// >>>>>>>  when I comment out below, the above code prints out "header id OK!!"

// <<<<<< here is where I have a problem compiling and can't find the right namespace path:
    // auto r = sbepp::make_const_view<three_arg_msg1::detail::messages::message_1>(addr, msg_size);
    auto r = sbepp::make_const_view<three_arg_msg1::detail::messages::message_1>(addr, msg_size);

    // let's pretend we got this buffer from an untrusted network and want to be
    // sure that the message is fully contained within given buffer.
    auto checked_size = sbepp::size_bytes_checked(r);
    if(!checked_size.valid) {
        std::cout << "bad message\n";
        exit(1);
    }

    // note: order doesn't matter, it's mixed for demo purpose
    auto dd = m.date();
    std::cout.write(dd.data(), dd.size());
    auto td = m.time();
    std::cout.write(td.data(), td.size());
    auto cd = m.meno();
    std::cout.write(td.data(), td.size());
    std::cout << "Done\n" ;
}

============= compile errors when I uncomment below "// <<<<<< here is where I have a problem compiling" =============

TE-SBE/test-sbepp/build$ make
Consolidate compiler generated dependencies of target sbetst1
[ 50%] Building CXX object CMakeFiles/sbetst1.dir/main.cpp.o
TE-SBE/test-sbepp/main.cpp: In function ‘int main()’:
TE-SBE/test-sbepp/main.cpp:50:50: error: no matching function for call to ‘size_bytes_checked(three_arg_msg1::detail::messages::message_1<const char>&)’
   50 |     auto checked_size = sbepp::size_bytes_checked(r);
      |                         ~~~~~~~~~~~~~~~~~~~~~~~~~^~~
In file included from TE-SBE/test-sbepp/three_arg_msg1/messages/msg1.hpp:7,
                 from TE-SBE/test-sbepp/main.cpp:7:
/usr/local/include/sbepp/sbepp.hpp:5534:5: note: candidate: ‘template<class View> sbepp::size_bytes_checked_result sbepp::size_bytes_checked(View, std::size_t)’
 5534 |     size_bytes_checked(View view, std::size_t size) noexcept
      |     ^~~~~~~~~~~~~~~~~~
/usr/local/include/sbepp/sbepp.hpp:5534:5: note:   template argument deduction/substitution failed:
TE-SBE/test-sbepp/main.cpp:50:50: note:   candidate expects 2 arguments, 1 provided
   50 |     auto checked_size = sbepp::size_bytes_checked(r);
      |                         ~~~~~~~~~~~~~~~~~~~~~~~~~^~~
make[2]: *** [CMakeFiles/sbetst1.dir/build.make:76: CMakeFiles/sbetst1.dir/main.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/sbetst1.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
TE-SBE/test-sbepp/build$

I believe line 46 ... 46: auto r = sbepp::make_const_view<three_arg_msg1::detail::messages::message_1>(addr, msg_size); is the problem but the examples have gaps and I can't figure what is the proper namespace path and object to put here.

Is there another complete example somewhere I can study?

Thanks

OleksandrKvl commented 1 month ago

First of all, you should never use things from the detail namespace directly. Namespace structure of generated headers is described here. You should use three_arg_msg1::messages::msg1 type.

About size_bytes_checked, yes, there's a mistake on examples page (they've never been compiled) but if you open its own documentation, you'll see that it has 2 parameters, the second one is the buffer size. Actually, compiler error tells you the same, candidate expects 2 arguments, 1 provided.

OleksandrKvl commented 1 month ago

Examples are pretty artificial, their intent is just to provide an overview of how the generated code can be used. It's better to check individual documentation pages or look how they are used in test files.