How to add a third party library into my Visual Studio 2013 solution

I am able to open, compile and run the openzwave cpp example app "MinOZW" found at:

https://code.google.com/p/open-zwave/source/browse/#svn%2Ftrunk%2Fcpp%2Fexamples%2Fwindows%2FMinOZW

I am also able to open, compile and run the open source webserver solution found at:

https://github.com/sunsetbrew/civetweb/tree/master/examples/embedded_cpp

However what I'd like to do is add the civetweb embeddable webserver to my openzwave example app solution in VS2014, and add it for use in the openzwave app.

I'm extremely new with VS and not clear how to do this.

Can anybody tell me:

a) the steps to add the civet embedded webserver referenced above to my openzwave example app solution "MinOZW" in VS2013 in the normal way?

b) a few lines of code to add somewhere in my openzwave app "Main.cpp" to see that it is working using the debugger (even if it doesn't really do anything, I can see in the debugger what is happening)

Thank you!
LVL 2
rustycpAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

sarabandeCommented:
i found some code which might help you.

http://root.cern.ch/root/htmldoc/src/TCivetweb.cxx.html

they used the civet webserver functions as base for their own c++ webserver classes.

from their code, I would think you need to do the following:

put the path to the folders with civetweb.h and civetweb.lib in your VC++ directories, in both the header and library sections of your project properties. this will be under Projects - your_project Properties -  Configuration Properties - VC++ directories. once the path is added, you should be able to #include <civetweb.h> in your code. to link with civetweb.lib add "civetweb.lib" at Projects - your_project Properties -  Configuration Properties - Linker - Input - Additional Dependencies.

Sara
0
Chris Raisin(Retired Analyst/Programmer)Commented:
You simply Click on project and select "Add Project".

You will end up with two projects in the same solution.

Make sure you mark the project which you want to "kick off" when the program starts as the "StartUp Project" by right clicking the project name in your Solution Explorer, then selecting "Set as Startup project" (be careful though, once the project becomes the startup project then the menu will say "Set Startup Projects..." which is a different thing ( a menu for manipulating Projects).
(This is what you do when you incorporate InstallSheild as your disbursement package).

Basically you can have lots of programs in one disbursement, one calling another if you wish).

Doing this will pull in all the required code from the extra project. You will just have to make sure you have all required external libraries ("Imports") required by the second Project referenced in its setup.

When you "Build your solution both projects will compile. When you "Publish" a sinclge setuup will be created but when it is run, both Projects will install. Using "Shell" calls in one application, you can open asecond application if you wish. I have never tried "sharing" code bwteen applications but I suppose it is possibleprovided it is in a DLL. I do not think thereis a way you can "reference" the second project from the first though and both application run a seperate self-contained entities. (But don't quote meon that.I just have not tried it!)

Cheers
Chris (Melbourne - Australia)
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
rustycpAuthor Commented:
Thanks guys, I will try this when I get home (at work right now, this is a hobby project for me).  This sounds like exactly the kind of guidance I needed.  I will report back here on the result.
0
Introducing Cloud Class® training courses

Tech changes fast. You can learn faster. That’s why we’re bringing professional training courses to Experts Exchange. With a subscription, you can access all the Cloud Class® courses to expand your education, prep for certifications, and get top-notch instructions.

rustycpAuthor Commented:
I did finally get the civetweb added and it will compile.  Mostly it was the paths in the project settings that were difficult to get right. But crasis the process you described got me looking in the right places to get it working.

Now actually adding some code from the civet server example works, but the thread seems to be blocking at the windows "GetMessage()" in the main loop.  My breakpoint stops there and never continues. So I'm guessing that's why it doesn't respond when I hit the http url with a browser, because it's hung up on GetMessage().  It only goes past GetMessage() when I do something in the app window, thus firing an event.  I thought civetserver was supposed to be multithreaded so I don't completely understand why it doesn't still fire it's event to handle the request.

So getting closer, will mess with it later today.

      while (GetMessage(&msg, NULL, 0, 0))
      {
            if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
            {
                  TranslateMessage(&msg);
                  DispatchMessage(&msg);
            }
      }
0
rustycpAuthor Commented:
Ok I fixed the issue of the GetMessage() function blocking by using this way of getting the messages, which times out:

BOOL GetMessageWithTimeout(MSG *msg, UINT to)
{
      BOOL res;
      UINT_PTR timerId = SetTimer(NULL, NULL, 1000, NULL);
      res = GetMessage(msg, NULL, 0, 0);
      KillTimer(NULL, timerId);
      if (!res)
            return FALSE;
      if (msg->message == WM_TIMER && msg->hwnd == NULL && msg->wParam == timerId)
            return FALSE; //TIMEOUT! You could call SetLastError() or something...
      return TRUE;
}


Still not quite working, but I can't help but think I'm getting close.
0
rustycpAuthor Commented:
The issue I'm having now is that when I start the debugger, it goes into the initialize function I created for the webserver, but then the app is not listening on the port, so clearly something is not happening right.  Below is my initialize function, which I call from my main function.  I'm not clear on what this line does:

      CivetServer server(options);

I was thinking that maybe the problem is that the "server" variable is not global, so it's gone as soon as I exit the function?  

void InitializeWebserver()
{

      Log::Write(LogLevel_Always, "Starting http api");

      const char * options[] = { "document_root", DOCUMENT_ROOT,
            "listening_ports", PORT, 0
      };

      CivetServer server(options);

      server.addHandler(EXAMPLE_URI, new ExampleHandler());
      server.addHandler(EXIT_URI, new ExitHandler());
      server.addHandler("/a", new AHandler());
      server.addHandler("/a/b", new ABHandler());
      server.addHandler("**.foo$", new FooHandler());

      //      printf("Browse files at http://localhost:%s/\n", PORT);
      //      printf("Run example at http://localhost:%s%s\n", PORT, EXAMPLE_URI);
      //      printf("Exit at http://localhost:%s%s\n", PORT, EXIT_URI);

      Log::Write(LogLevel_Always, "http api successfully started");

}
0
rustycpAuthor Commented:
That is indeed the problem, when I put this at the end of that function:

      while (!exitNow) {
            Sleep(1000);
      }


the web server runs correctly.

So I am thinking the "server" var needs to be global so it's not lost when I leave the function. But I'm not sure how to do that.  Probably if I understand what this line does then I'll have a better idea:

      CivetServer server(options);
0
sarabandeCommented:
but the thread seems to be blocking at the windows "GetMessage()" in the main loop.  

I hope the message loop is in your main thread and not in a worker thread. you may not process dialog messages in  a worker thread. the GetMessage is not thread-safe and by calling TranslateMessage and DispatchMessage you are calling functions of the main thread (the dialog thread) asynchronously from thread. moreover, you were removing and handling all the messages what makes the main thread freezing as it has no messages to perform. if the thread has its own (pseudo) window, you may process the messages of this window only. but that doesn't seem the case here.

if you got data in a thread and want to send them to the main dialog, you need to send them by calling PostMessage(yourMainHwnd, yourMessageId, (WPARAM)yourThreadId, (LPARAM)ptrToData)  which is thread-safe.

in your main thread you would catch the message by providing an appropriate event handler. this handler now is synchronous with the main thread and you can safely process the messages.

if you post your code here (please use code tags) we could check whether your design is thread-safe.

Sara
0
Chris Raisin(Retired Analyst/Programmer)Commented:
I can't help you there since I am not a "C" programmer and I have not actually dealt with web servers etc.

Sorry...but your original question related only to making two projects "co-habit a solution" and hopefully that has been covered.

These extra questions regarding the coding should be submitted as a seperate question for consideration by C/C++/C#  experts.

Cheers  
Chris   :-)
0
sarabandeCommented:
I was thinking that maybe the problem is that the "server" variable is not global,
instead of a global server, you may use a little helper class which provides the server as a singleton.

//css.h  civet server singleton

#ifndef CSS_H
#define CSS_H

#include <civetserver.h>

class CSS
{
      // private constructor prevents creating an instance
      CSS() {}
public:
      static CivitServer & GetInstance() 
      {
            static CivitServer theServer;
            return theServer;
      }
};

Open in new window

#endif

using that class you can access the server singleton from everywhere by code like

CivetServer & server = CSS::GetInstance();

Open in new window


Sara
0
sarabandeCommented:
note, even if the civetweb is multi-threaded it doesn't mean that you could access shared data without protection from multiple threads.

instead you may use a critical section instance to make all access to shared data or shared objects exclusively.

Sara
0
rustycpAuthor Commented:
Both in the class example and if I just use code to declare a global variable, I get the error "No suitable constructor exists for CivetServer."

So for example if I change this code:

      CivetServer server(options);

to this:

        CivetServer server = new CivetServer(options);

I get the error "No suitable constructor exists for CivetServer"

What does that syntax do exactly? I've having a hard time googling for it because I don't know what it's called.
0
rustycpAuthor Commented:
ok gonna start a new question thread per the suggestion, thank you
0
sarabandeCommented:
 I get the error "No suitable constructor exists for CivetServer."

Open in new window

the error means, that CivetServer hasn't a default constructor (taking no argument).

I see in your code that you pass an argument 'options' when you construct the CivetServer instance.

that also must be done in the CSS::GetInstance function:

class CSS
{
      ...     
      static CivitServer & GetInstance() 
      {
           const char * options[] = { "document_root", DOCUMENT_ROOT,
             "listening_ports", PORT, 0   };

            static CivitServer theServer(options);
            return theServer;
      }

Open in new window

when the function was called it returns a reference (not a pointer) to the static CivetServer object of the GetInstance function. the object was constructed with the first call and keeps alive until your program ends. it can be called from different threads without problems. Because the function is static, it always would return a reference to one and only singleton instance of CivetServer (as long as you don't use the class in different executables (.exe or .dll)

CivetServer server = new CivetServer(options);

Open in new window

in c++ the operator 'new' returns a pointer. hence the above statement doesn't compile because it translates to

CivetServer server(pointer_to_CivitServer);

Open in new window


what is wrong, cause the constructor of CivetServer takes an array of const char pointers like the 'options' array.

the following code would compile:

CivetServer * server = new CivetServer(options);

Open in new window

however, you would need to share the pointer variable 'server' between your functions and your threads (for example by making it a global variable).

generally, you should avoid to using global variables as their usage is much more error-prone. global pointers are worse because you will have troubles to free the allocation at end of program as there is no instance which is responsible for this.

Sara
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.