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

时间:2009-12-14 13:16:35

标签: c# c++ python dll web-based

我们有一个用C ++编写的成熟的Windows桌面应用程序。应用程序的GUI位于Windows DLL的顶部,它完成GUI的大部分工作(它是引擎的一种)。它也是用C ++编写的。我们正在考虑将Windows应用程序转换为基于Web的应用程序,原因有多种。

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

所以,问题是:鉴于我需要在后端使用C ++ DLL来完成应用程序的工作,您建议在用户的浏览器和C ++ dll之间使用哪种技术堆栈?我们可以假设Web服务器将是Windows。

一些选项:

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

    关注:

    • 如果可以避免,我宁愿不使用C ++作为Web框架 - 我认为像Python和C#这样的语言在开发时间方面更加强大和高效。
    • 我担心我使用.NET解决方案混合托管代码和非托管代码我要求许多难以调试的小问题(纯粹的轶事证据)
    • 使用Python图层也是如此。任何稍微偏离常规的东西都会让我担心,因为如果这是一个可行的长期解决方案,我没有太多证据。

4 个答案:

答案 0 :(得分:10)

  

另见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 ++或pinvoke(但是如果你已经在C ++端使用COM了,这是一个选项,只要您使用VB6可以处理的COM子集)。
  • .NET无法访问任何托管C ++对象,但它可以使用Pinvoke访问简单的C函数,因此无论你做什么,都需要在C ++站点上使用某种桥接层。
  • 看看您是否可以使用Silverlight而不是Web,如果您能够(安装问题等),它将为您节省大量的开发时间。 (并且允许您定位Microsoft手机)
  • 检查“端口到网络”的业务案例是否非常强大,并且需要比您想象的要长很多,是使用终端服务器等托管的选项您的客户
  • 考虑线程和多用户访问,例如你的dll是否认为它只被一个用户使用?
  • 仅仅因为您正在开发新的Web版本,即使您已经发布了Web版本,您仍然可以让客户要求更改桌面版本。我在过去发现,现有客户并不总是希望转移到网络应用程序。

(抱歉,我不知道是否匹配Python,但是如果你还没有相关的技能,我会说你已经知道微软的调试器等,你会坚持使用Microsoft堆栈)


(我认为将复杂的应用程序作为非常大的痛苦移植到网络上,最好尽可能避免痛苦,但有时你没有选择,只需要最大限度地减少痛苦。如果您从未处理过移动到网络中的大型应用程序(通常需要很多年的工作),那么您只是不知道自己要做什么!

答案 1 :(得分:4)

3- Python是解决方案。

在python中创建一个sigle入口点接口,它只接受函数的名称和传递给函数本身的params列表。你将有一些东西可以立即开始实验,看看第一个功能网络原型真正需要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()

答案 2 :(得分:2)

我会说选项2是要走的路。如果你在.Net中创建一个接口到你的DLL,以确保你在需要时正确释放你的内存等我没有看到问题。如果您可以在DLL中重用业务逻辑,并且基本上可以对您的DLL进行Web调用,那么很棒。

我唯一关心的是你的DLL的API。 ASP.Net显然是一个多用户多线程应用程序。您的API是否已设计为采用此功能,因为大多数Windows窗体应用只会有一个用户驱动它们(想象一下,如果您的应用中的每个表单都可以同时由多个用户打开)。

答案 3 :(得分:1)

由于没有人提及过,Wt怎么样?

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