Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Transitioning from desktop app written in C++ to a web-based app

We have a mature Windows desktop application written in C++. The application's GUI sits on top of a windows DLL that does most of the work for the GUI (it's kind of the engine). It, too, is written in C++. We are considering transitioning the Windows app to be a web-based app for various reasons.

What I would like to avoid is having to writing the CGI for this web-based app in C++. That is, I would rather have the power of a 4G language like Python or a .NET language for creating the web-based version of this app.

So, the question is: given that I need to use a C++ DLL on the backend to do the work of the app what technology stack would you recommend for sitting between the user's browser and are C++ dll? We can assume that the web server will be Windows.

Some options:

  1. Write a COM layer on top of the windows DLL which can then be access via .NET and use ASP.NET for the UI
  2. Access the export DLL interface directly from .NET and use ASP.NET for the UI.
  3. Write a custom Python library that wraps the windows DLL so that the rest of the code can be written.
  4. Write the CGI using C++ and a C++-based MVC framework like Wt

Concerns:

  • I would rather not use C++ for the web framework if it can be avoided - I think languages like Python and C# are simply more powerful and efficient in terms of development time.
  • I'm concerned that my mixing managed and unmanaged code with one of the .NET solutions I'm asking for lots of little problems that are hard to debug (purely anecdotal evidence for that)
  • Same is true for using a Python layer. Anything that's slightly off the beaten path like that worries me in that I don't have much evidence one way or the other if this is a viable long term solution.
like image 296
Karim Avatar asked Dec 14 '09 13:12

Karim


3 Answers

See also Can a huge existing application be ported to the web? How?

Sorry there are no good solutions, just less bad ones....

Firstly as you already develop for windows I am assuming that you are used to using the Microsoft development tools, I would not give the same answer for a desktop application that is coming from unix (or Mac).

Some random thoughts and pointers.

  • I would make use of Asp.net most likely Aps.net MVC.
  • I would try to wrap in C++ classes in some nice high level .net class, maybe using Managed C++ / CLI.
  • Using COM is likely to be a lot of work on the C++ side and does not make the .NET easy, so I would avoid COM in favour of managed C++ or pinvoke (However if you are allready using COM on the C++ side, this it is an option, provided you are using the subset of COM that VB6 could cope with).
  • .NET can't access none managed C++ object, but it can access simple C function using Pinvoke, so whatever you do some sort of bridging layer will be needed on the C++ site.
  • See if you can use Silverlight rather than the web, if you are able to (install issues etc) it will save you a lot of development time. (And lets you target Microsoft Phones as well)
  • Check that the business case for a “port to the web” is very strong and it will take a lot longer then you think!, Is hosting with terminal server etc an option for your customers?
  • Think about threading and multi user access, e.g. does your dll assume it is only being used by one user?
  • Just because you are working on a new web version, you will still get customers demanding changes to the desktop version even after you have shipped the web version. I have found in the past that current customers don’t always wish to move to a web app.

(Sorry I don’t know match about Python, however if you don’t already have skills in it I would say stick on the Microsoft stack as you already know the Microsoft debugger etc)


(I think of porting complex applications to the web as a very big pain, it is best to avoid pain when possible however sometimes you are given no option and just have to minimize the pain. If you have never worked on large applications that are in the process (normally many years work) of being ported to the web, you just don’t know what you are letting yourself in for!)

like image 190
Ian Ringrose Avatar answered Oct 08 '22 02:10

Ian Ringrose


3- Python is the solution.

Make a sigle entry point interface in python that takes only the name of the function and a list of params to pass to the function itself. You will have something to start experimenting straight away and see which functions of the DLL are really needed for the first functional web prototype.

A stub for a single functions module is

#include <Python.h>
#include <string.h>

int int_function(int a){
    return a +=1;
}

static PyObject *
exec_lib(PyObject *self, PyObject *args)
{
    char *fun_name;
    PyObject *func_name = PyTuple_GetSlice(args, 0,1);
    PyObject *res;

    if (!PyArg_ParseTuple(func_name, "s", &fun_name))
         return NULL;
    Py_DECREF(func_name);
    if (strncmp("int_function", fun_name, 1024) == 0)
    {
        int i;
        PyObject *fun_args = PyTuple_GetSlice(args, 1,20);
        if (!PyArg_ParseTuple(fun_args, "i", &i))
            return NULL;
        Py_DECREF(fun_args);
        res = Py_BuildValue( "i", int_function(i));
    } else {
        Py_INCREF(Py_None);
        res = Py_None;
    }

    return res;
}



PyMethodDef methods[] = {
    {"exec_lib", exec_lib, METH_VARARGS, " Returns"},
    {NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC 
initlibwrap()
{
    (void) Py_InitModule("libwrap", methods);
}

can be compiled with a setup.py file

from distutils.core import setup, Extension

setup(name = "libwrap",
      version = "1.0",
      ext_modules = [Extension("libwrap", ["my_library_wrap.cpp"])])

and used in a simple web server like

from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
import libwrap


def int_function(value):
    return libwrap.exec_lib("int_function", value)

print int_function(10)

class MyHandler(BaseHTTPRequestHandler):

    def do_GET(self):
        self.send_response(200)
        value = 'Error'
        try:
            value = int_function()
        except:
            import traceback
            traceback.print_stack()
        self.wfile.write(value)

def main():
    try:
        ip ='localhost'
        port = 8080
        server = HTTPServer((ip,port), MyHandler)
        server.serve_forever()
    except KeyboardInterrupt:
        server.socket.close()

if __name__ == '__main__':
    main()
like image 38
fabrizioM Avatar answered Oct 08 '22 04:10

fabrizioM


I would say option 2 is the way to go. Provided that you create an interface in .Net to your DLL to make sure you correctly release your memory etc. when needed I don't see an issue. If you can reuse your business logic in your DLL and basically make a web call into your DLL then great.

My only concern would be your DLL's API. ASP.Net is obviously a multiple user multi-threaded application. Has your API been designed to take this, given that most windows forms apps will only have one user driving them (imagine if every form in your app could be opened by more than one user all at the same time).

like image 44
Spence Avatar answered Oct 08 '22 04:10

Spence