代码之家  ›  专栏  ›  技术社区  ›  Karim

从C++编写的桌面应用程序到基于Web的应用程序的转换

  •  5
  • Karim  · 技术社区  · 15 年前

    我们有一个成熟的Windows桌面应用程序,用C++编写。应用程序的图形用户界面位于Windows动态链接库之上,该动态链接库为图形用户界面(这是一种引擎)完成大部分工作。它也是用C++编写的。出于各种原因,我们正在考虑将Windows应用程序转换为基于Web的应用程序。

    我希望避免在C++中为这个基于Web的应用程序编写CGI。也就是说,我宁愿拥有像Python这样的4G语言或.NET语言的能力来创建这个应用程序的基于Web的版本。

    所以,问题是:假设我需要在后端使用C++ DLL来完成应用程序的工作,你认为在用户浏览器和C++ DLL之间坐什么样的技术堆栈?我们可以假设Web服务器是Windows。

    一些选项:

    1. 在Windows DLL的顶部编写一个COM层,然后可以通过.NET访问该层,并将ASP.NET用于UI
    2. 直接从.NET访问导出dll接口,并使用ASP.NET作为UI。
    3. 编写一个自定义的python库,该库包装Windows dll,以便可以编写其余的代码。
    4. 用C++和基于C++的MVC框架编写CGI Wt

    关注:

    • 如果不是可以避免的话,我宁愿不使用C++来处理Web框架——我认为Python和C.*之类的语言在开发时间方面更强大和高效。
    • 我担心我将托管和非托管代码与一个.NET解决方案混合在一起,我要求解决许多很难调试的小问题(纯粹是轶事证据)。
    • 使用Python层也是如此。任何稍微偏离老路的事情都让我担心,因为如果这是一个可行的长期解决方案,我没有太多的证据。
    4 回复  |  直到 14 年前
        1
  •  10
  •   Community George Stocker    7 年前

    也见 Can a huge existing application be ported to the web? How?

    对不起,没有好的解决方案,只有不那么坏的解决方案……

    首先,由于您已经为Windows开发了,我假设您已经习惯了使用Microsoft开发工具,对于来自Unix(或Mac)的桌面应用程序,我不会给出相同的答案。

    一些随机的想法和指示。

    • 我会使用ASP.NET,很可能是APS.NET MVC。
    • 我会尝试在一些高级的.NET类中使用C++类来包装,也许使用 Managed C++ / CLI .
    • 使用COM很可能是C++方面的大量工作,并不能使.NET变得容易,所以我将避免COM支持托管C++或PNECKE(但是如果您在C++侧使用COM,那么这是一个选项,前提是您使用的是VB6可以处理的COM子集)。
    • .NET不能访问没有管理的C++对象,但是它可以使用pNoCKE访问简单的C函数,所以不管你做什么,都需要在C++站点上建立某种桥接层。
    • 看看您是否可以使用Silverlight而不是Web,如果您能够(安装问题等),它将为您节省大量的开发时间。(也让您以微软手机为目标)
    • 检查Web_端口的业务案例是否非常强大,并且需要 比你想象的要长得多! ,正在承载终端服务器等选项 你的顾客 是吗?
    • 考虑线程和多用户访问,例如,您的DLL是否假定它仅由一个用户使用?
    • 仅仅因为您正在开发一个新的Web版本,即使您已经发布了Web版本,您仍然会有客户要求更改桌面版本。我过去发现,现在的客户并不总是希望使用Web应用程序。

    (很抱歉,我不知道python的匹配,但是如果您还没有相关技能,我会说像您已经知道的Microsoft调试器那样,坚持使用Microsoft堆栈)


    (我认为将复杂的应用程序移植到Web上是 非常大的疼痛 尽可能避免疼痛,但有时你没有选择,只能这样做。 减轻痛苦 .如果您从未在大型应用程序上工作过,而这些应用程序正处于移植到Web的过程中(通常需要很多年的工作),那么您只是不知道自己要做什么!)

        2
  •  4
  •   fabmilo    15 年前

    3-解决方案是python。

    在python中创建一个sigle入口点接口,该接口只接受函数名和要传递给函数本身的参数列表。您将有一些东西可以立即开始试验,看看第一个功能性Web原型真正需要哪个DLL函数。

    单个功能模块的存根是

    #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);
    }
    

    可以用setup.py文件编译

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

    在一个简单的网络服务器中使用

    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()
    
        3
  •  2
  •   Spence    15 年前

    我会说第二种选择是可行的。如果您在.NET中创建一个到您的DLL的接口,以确保在需要时正确释放内存等,我看不到问题。如果您可以在您的DLL中重用您的业务逻辑,并基本上对您的DLL进行Web调用,那么就太好了。

    我唯一关心的是您的DLL的API。ASP.NET显然是一个多用户多线程应用程序。如果大多数Windows窗体应用程序只有一个用户来驱动它们,那么您的API是否设计为采用这种方式(假设应用程序中的每个窗体都可以同时由多个用户打开)。

        4
  •  1
  •   t.g.    15 年前

    既然没人提过,那怎么样 Wt .

    如果您不在寻找基于浏览器的用户界面,那么有很多C++库可以将本地应用程序扩展到基于Web的应用程序, POCO 是其中之一。如果你坚持使用Windows平台, WWSAPI 对C/C++开发人员来说真的很酷。