0

Background: I have many small c++ programs that all use the same static library. I'm now implementing thrift as a middle layer so that I can run the small c++ programs on a different computer from the static library. I can't change the c++ programs, so I am making a "fake" static library that looks like the original, but is actually a thrift client that calls the real static library.

Issue: How can I make the static library so that the c++ programs will automatically open the socket when it opens the library, and closes the socket when the program exits??

Usually thrift clients use a main method that opens the socket in the beginning and closes it in the end. I can have the library check if the socket is open before every method call, but I don't know how to close the socket. Is there any problem with leaving it open?

Community
  • 1
  • 1
woojoo666
  • 7,801
  • 7
  • 45
  • 57

1 Answers1

1

One approach might be to create a C++ class in your library with a single local static instance. Since the instance will be constructed on first call and destroyed on unload, you can connect and disconnect using the constructor/destructor, something like this:

#include <boost/shared_ptr.hpp>
#include <thrift/transport/TSocket.h>
#include <thrift/protocol/TBinaryProtocol.h>
#include "gen-cpp/mySvc.h"                  

using namespace apache::thrift::transport;  
using namespace apache::thrift::protocol;   

class ThriftProxy {
public:
    ThriftProxy() :
        trans(new TSocket("myhost", 8585)),
        proto(new TBinaryProtocol(trans)),
        client_(proto)
    {
        trans->open();
    }

    ~ThriftProxy()
    {
        trans->close();
    }

    static mySvcClient & client() 
    {
        static ThriftProxy proxy;
        return proxy.client_;
    }    

private:
    boost::shared_ptr<TSocket> trans;
    boost::shared_ptr<TProtocol> proto;
    mySvcClient client_;
};

the functions in your lib can then call through to the Apache Thrift server using the ThriftProxy::client() method:

int exportedFunc(int i) {
    return ThriftProxy::client().myRPCFunc(i);
}

Note: In most cases adding a TBufferedTransport or TFramedTransport to the I/O stack is a good idea to reduce small writes to the network. Left out here to keep the example simple.

codeSF
  • 1,162
  • 9
  • 16
  • Normally when I make a thrift client, and I run it without running the server first, I get a `TSocket::open() connect()` error, but now when I use this library, I get a segmentation fault. Everything works when I start the server, but do you know how I can get the old error message back? – woojoo666 Jul 18 '13 at 19:49
  • nvm fixed it. `static ThriftProxy proxy` initializes `ThriftProxy` before many of the other thrift objects, so `trans->open` causes a segmentation fault. instead I used a [construct on first use](http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Construct_On_First_Use) wrapper for `ThriftProxy` – woojoo666 Jul 18 '13 at 23:50
  • 1
    @woojoo666: init on 1st call is a nice improvement, added above, much better example – codeSF Jul 22 '13 at 00:38