?
Solved

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

Posted on 2014-10-12
14
Medium Priority
?
821 Views
Last Modified: 2014-10-14
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!
0
Comment
Question by:rustycp
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 5
  • 2
14 Comments
 
LVL 35

Expert Comment

by:sarabande
ID: 40376951
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
 
LVL 13

Accepted Solution

by:
Chris Raisin earned 2000 total points
ID: 40376992
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
 
LVL 2

Author Comment

by:rustycp
ID: 40377287
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
Prepare for your VMware VCP6-DCV exam.

Josh Coen and Jason Langer have prepared the latest edition of VCP study guide. Both authors have been working in the IT field for more than a decade, and both hold VMware certifications. This 163-page guide covers all 10 of the exam blueprint sections.

 
LVL 2

Author Comment

by:rustycp
ID: 40379575
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
 
LVL 2

Author Comment

by:rustycp
ID: 40379740
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
 
LVL 2

Author Comment

by:rustycp
ID: 40379750
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
 
LVL 2

Author Comment

by:rustycp
ID: 40379782
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
 
LVL 35

Expert Comment

by:sarabande
ID: 40379847
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
 
LVL 13

Expert Comment

by:Chris Raisin
ID: 40379866
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
 
LVL 35

Expert Comment

by:sarabande
ID: 40379887
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
 
LVL 35

Expert Comment

by:sarabande
ID: 40379905
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
 
LVL 2

Author Comment

by:rustycp
ID: 40380398
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
 
LVL 2

Author Comment

by:rustycp
ID: 40380502
ok gonna start a new question thread per the suggestion, thank you
0
 
LVL 35

Expert Comment

by:sarabande
ID: 40380547
 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

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Update (December 2011): Since this article was published, the things have changed for good for Android native developers. The Sequoyah Project (http://www.eclipse.org/sequoyah/) automates most of the tasks discussed in this article. You can even fin…
What my article will show is if you ever had to do processing to a listbox without being able to just select all the items in it. My software Visual Studio 2008 crystal report v11 My issue was I wanted to add crystal report to a form and show…
The viewer will learn how to use NetBeans IDE 8.0 for Windows to connect to a MySQL database. Open Services Panel: Create a new connection using New Connection Wizard: Create a test database called eetutorial: Create a new test tabel called ee…
The viewer will learn how to use and create keystrokes in Netbeans IDE 8.0 for Windows.

770 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question