LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Referenced Parameters in C library not working on Compact RIO

High level 

I want to use Google Protobuf on my Compact RIO.  I have it 90% of the way there and running into issues.

 

Details

I'm a long time C++ developer who's newish to LabVIEW.  I'm using C to create a cross-compiled library to use on a Compact RIO (9025) with LabVIEW code.  I'm using Linux (Ubuntu 14.04.1) with a VxWorks toolchain and CMake to create the library.  I copy it over manually (looking for a better solution to that here), call it from LabVIEW via a Call Library Function, and assuming I'm doing simple things it works great!  Here's a quick sample of what I have that works:

 

My C code

 

extern "C" double addNums(double in1, double in2)
{
    return in1 + in2;
}

extern "C" double multNums(double in1, double in2)
{
    return in1 * in2;
}

Which I cross compile to a VxWorks binary and copy over to the cRIO.

 

Then on the LabVIEW side, I have this.

 

lvAddnums.png

I run it on the target cRIO and all works great.

 

I mentioned protobuf.  Cross compiling the full blown protobuf library for VxWorks proved to be a near (if not 100%) impossible task.  So I found and am using Nanopb.  I'm able to cross compile and get the following code using Nanopb to actually run on the cRIO and spit out the expected response:

 

extern "C" double testPbuf()
{
    uint8_t buffer[128];
    size_t message_length;
    bool status;

    std::ofstream file;
    file.open("testOutput.bin", std::ios::out | std::ios::binary);

    //! Create a message
    {
        ExampleMsg message;
        message.value = 13;
        pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
        status = pb_encode(&stream, ExampleMsg_fields, &message);
    }

    //! Decode the message
    {
        ExampleMsg message;
        pb_istream_t stream = pb_istream_from_buffer(buffer, message_length);
        status = pb_decode(&stream, ExampleMsg_fields, &message);

        return message.value;
    }

    return 0;
}

Not terribly important, but if you know protobuf, here's the proto message I'm using

message ExampleMsg {
    required int32 value = 1;
}

So then I call this function from LabVIEW very simply:

lvPbtest.png

I run this and it works!  I see my 13 as expected.  Jump for joy, protobuf works on the Compact RIO!  Ok no jumping yet...

 

Now what I want to do is get the C library to generate and output the actual serialized protobuf message because I need to send it over UDP from the Compact RIO.  So here's my attempt so far:

 

extern "C" const void getPacket(uint8_t* packet)
{
    uint8_t buffer[128];
    uint16_t packetSize;
    bool status;

    ExampleMsg msg;
    pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
    msg.value = 14;
    status = pb_encode(&stream, ExampleMsg_fields, &msg);
    packetSize = stream.bytes_written;

    //! If something failed we should see an 'X' in the first byte
    if (!status)
    {
        buffer[0] = 'X';
    }

    memcpy(packet, buffer, packetSize);
}

And on the LabVIEW side, I'm initializing an array of unsigned int 8s to the proper size and feeding it into the function, and reading the packet parameter as output.

lvPbPacket.png

When I run this I never get any output on packet except whatever I set the initializer to.  I have also changed the code to try to output a string as a parameter argument, with this declaration:

extern "C" const void getPacket(char* packet)

And memcpy() appropriately and can't seem to get the output properly in LabVIEW using strings in place of the U8s.  I need to figure out how to get this serialized protobuf data into LabVIEW so I can send it over UDP as a message.

 

I have seen several examples in the LabVIEW installation directory, but they're referring to objects and libraries which are meant for Windows DLLs and not easily used in a cross compiled environment.  I also have seen many threads on here relating to this but none have helped so far.  Any help would be greatly appreciated!

 

0 Kudos
Message 1 of 3
(2,881 Views)

impala454,

 

Have you tried writing the serialized packet to a binary file on the cRIO and reading it into LabVIEW before sending it?

Aaron L.
Applications Engineer
National Instruments
0 Kudos
Message 2 of 3
(2,788 Views)

I would hate to do a file write to solve this as it would add a whole new lag to the system.  I did end up with a solution, which is essentially what I posted above.  It seems like the real issue I was having was that the dll was not being reloaded on subsequent rebuilds/tests.  So I would make changes to the DLL to test and they wouldn't be reflected even when I copied the DLL to the Compact RIO.  Turns out I have to completely close the project and re-open it if I change the dll file.  This is really strange behaviour.  I could even *delete* the DLL from the Compact RIO and the VI would still run with the previous "copy" somehow.

 

Anyhow it looks like I have protobuf working from the Compact RIO, though still have a few issues with encoding certain data types.  If anyone is interested in the full solution I may do a write up.

0 Kudos
Message 3 of 3
(2,765 Views)