zoukankan      html  css  js  c++  java
  • 用 WebService 实现 Silverlight 客户端调用第三方动态链接库(Fortran DLL)的具体过程

          出于安全性考虑,Web端调用第三方动态链接库则没有本地调用动态链接库那么方便,关于本地调用第三方动态链接库,可以参考之前的一篇博文:

    http://www.cnblogs.com/potential/archive/2012/11/05/2755899.html

    本文主要将如何在Web端调用第三方动态链接库。

    前言:

    之前在做毕业设计的时候用的是Silverlight,曾经用Fortran写了一个大气污染物扩散模型的计算代码,但是在用Silverlight之前都是本地调用,开始的时候也是按照本地调用,发现不行。经查阅,可以通过WebService,或者WCF等方式来实现。现总结如下:

    第一步:

    首先新建一个Silverlight项目,界面如下:

    XAML代码:

    <UserControl x:Class="SilverlightApplication.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        d:DesignHeight="300" d:DesignWidth="400">
    
        <Grid x:Name="LayoutRoot" Background="White" HorizontalAlignment="Center">
            <TextBox Height="23" HorizontalAlignment="Left" Margin="25,55,0,0" Name="textBoxA" VerticalAlignment="Top" Width="78" />
            <TextBox Height="23" HorizontalAlignment="Left" Margin="141,55,0,0" Name="textBoxB" VerticalAlignment="Top" Width="85" />
            <TextBlock Height="23" HorizontalAlignment="Left" Margin="274,55,0,0" Name="AddResulttextBlock" VerticalAlignment="Top" Width="76" />
            <TextBlock Height="23" Margin="109,112,0,0" Name="RandomtextBlock" Text="" VerticalAlignment="Top" HorizontalAlignment="Left" Width="229" />
            <TextBlock Height="23" HorizontalAlignment="Left" Margin="119,55,0,0" Name="textBlock2" Text="+" VerticalAlignment="Top" />
            <Button Content="计算" Height="23" HorizontalAlignment="Left" Margin="144,265,0,0" Name="CaculationButton" VerticalAlignment="Top" Width="75" />
            <TextBlock Height="23" HorizontalAlignment="Left" Margin="249,58,0,0" Name="textBlock3" Text="=" VerticalAlignment="Top" />
            <TextBlock Height="23" HorizontalAlignment="Left" Margin="25,112,0,0" Name="textBlock4" Text="生成的随机数:" VerticalAlignment="Top" />
            <TextBlock Height="23" HorizontalAlignment="Left" Margin="109,156,0,0" Name="SorttextBlock" Text="" VerticalAlignment="Top" Width="229" />
            <TextBlock Height="23" HorizontalAlignment="Left" Margin="26,156,0,0" Name="textBlock6" Text="排序后的结果:" VerticalAlignment="Top" />
            <TextBlock Height="23" HorizontalAlignment="Left" Margin="26,197,0,0" Name="textBlock1" Text="数组的最大值:" VerticalAlignment="Top" />
            <TextBlock Height="23" HorizontalAlignment="Left" Margin="109,197,0,0" Name="MaxValuetextBlock" Text="" VerticalAlignment="Top"  Width="229" />
        </Grid>
    </UserControl>

    第二步:  

    将Fortran动态链接库编译后的Dll文件,放到Silverlight Web项目的bin文件夹下。

    下面给出了本文的Fortran DLL示例代码:

    DOUBLE PRECISION FUNCTION ADD(A,B)
    !DEC$ ATTRIBUTES DLLEXPORT::ADD
    !DEC$ ATTRIBUTES STDCALL,ALIAS:'Add'::ADD
        DOUBLE PRECISION:: A,B
        ADD=A+B
    END
    
    FUNCTION SORTANDFINDMAX(ARRAY,LENGTH)
    !DEC$ ATTRIBUTES DLLEXPORT::SORTANDFINDMAX
    !DEC$ ATTRIBUTES STDCALL,ALIAS:'Sortandfindmax'::SORTANDFINDMAX
    DOUBLE PRECISION ::ARRAY(LENGTH)
    INTEGER::I,J
    DOUBLE PRECISION::TEMP
    DO I=1,LENGTH-1
        DO J=I+1,LENGTH
            IF(ARRAY(I).GT.ARRAY(J)) THEN
                TEMP=ARRAY(I)
                ARRAY(I)=ARRAY(J)
                ARRAY(J)=TEMP
                END IF
        END DO
        END DO
    END

    第三步:

    在Silverlight Web项目中添加新建项——选择WebService

    这里我们将WebService命名为CaculationWebService.之后点击添加。

    第 四 步:

    通过WebService来调用Fortran DLL.

     由于Web是运行在客户端,因此无法像本地一样调用服务器的DLL,因此这里我们借助WebService的方式实现。

    在第三步之后,我们的Web项目中会增加如下两个文件,也就是我们新建的WebService项。

    打开CaculationWebService.asmx.cs。编写调用FORTRAN DLL的代码。

    注意WebService是运行在服务器端的,因此,调用Fortran DLL的代码和本地一致。下面给出了本文的示例代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Services;
    using System.Runtime.InteropServices;
    
    namespace SilverlightApplication.Web
    {
        /// <summary>
        /// Summary description for CaculationWebService
        /// </summary>
        [WebService(Namespace = "http://tempuri.org/")]
        [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
        [System.ComponentModel.ToolboxItem(false)]
        // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
        // [System.Web.Script.Services.ScriptService]
        public class CaculationWebService : System.Web.Services.WebService
        {
    
            [WebMethod]
            public double AddCaculation(double a,double b)
            {
                return Add(a,b);
            }
            
            [WebMethod]
            public double [] SortCaculation(double []array, int length)
            {
                //在服务器端执行的语句
                 Sortandfindmax(array, length);
                //在服务端返回排序后的结果
                 return array;
            }
            //在服务器端调用Fortran DLL
            [DllImport("TestDll.dll", CallingConvention = CallingConvention.Cdecl)]
            private  static extern double Add(double a, double b);
    
            [DllImport("TestDll.dll", CallingConvention = CallingConvention.Cdecl)]
            private  static extern void Sortandfindmax(double[] array, int length);
    
        }
    }

    注意Web调用Fortran Dll时,如果需要返回,则不能直接返回给客户端

    比如在本地调用时,我们直接传入数组,完成调用后,数组的值就会发生改变。

    但是在Web端则不是,因为本地调用直接修改了数组的地址,但是由于Web调用是在服务器端进行的,因此无法修改我们本机的地址,因此传入的数组无论怎样也不会发生改变

    而Web调用可以通过给方法增加一个返回值来实现,比如传入了一个数组,我们可以在Web端将这个结果返回,然后再通过WebMethod返回给客户端,并在在客户端通过注册Completed事件的响应函数,获得最后的结果。

    关于服务器端的WebService搭建工作已经完成。

    第 五 步:

    验证WebService是否能够正常运行。以上我们搭建好了WebService,在添加WebService的引用之前,最好测试一下其是否能够正常工作。步骤如下:

    右键Silverlight Web项目中的WebService的asmx文件,选择view in browser.

    此时没有错误,在浏览器中会出现如下视图:

    我们可以看见有两个方法,随便点击一个方法,例如AddCaculation.则会出现验证方法的界面:

    我们输入以上参数:3和4,点击Invoke.如果成功调用则会出现正确的结果,并以XML的方式返回。

    如下图所示:

    以上的过程便是验证WebService的过程,验证成功之后,下面开始客户端调用的工作。

    第六步:

        首先需要在Silverlight项目中添加WebService的引用,如图所示:

    接着点击Discover,就会找到我们之前新建的WebService.如下图所示:

    将服务的引用名称设置为CaculationService,之后点击OK,从以上途中我们也可以发现,我们添加的WebService包含了两个方法:一个是AddCaculation,一个是SortCaculation.我们将在后续的工作中调用这两个方法。

    最后,在Silverlight项目中则会出现WebService的引用。

    第 七 步:

    在Silverlight项目中编辑调用WebService的代码:

    这里值得需要注意的就是调用WebService需要注意的参数类型匹配问题。之前我们在WebService定义了一个SortCaculation方法,其输入参数是double数组类型的。虽然在Web端是DOUBLE类型的数组,但是我们在客户端调用的时候会发现其类型变成了ArrayOfDouble,这是为什么呢?原因是WebService的返回结果及参数是以XML形式传递的,而在XML中,数组类型的数据则会变成ArrayOf<类型名>,例如double类型的数组则就变成了ArrayOfDouble。

    关于调用的过程:

    1. 首先声明一个WebService引用的实例。
    CaculationService.CaculationWebServiceSoapClient client = new CaculationWebServiceSoapClient();

          2.  注册调用方法完成事件的响应函数

    client.AddCaculationCompleted += new EventHandler<AddCaculationCompletedEventArgs>(client_AddCaculationCompleted);
    
    client.SortCaculationCompleted += new EventHandler<SortCaculationCompletedEventArgs>(client_SortCaculationCompleted);

          3.  在Button Click事件中请求WebService(调用WebService的计算方法)。

    例如:

    client.AddCaculationAsync(Convert.ToDouble(textBoxA.Text),Convert.ToDouble(textBoxB.Text));
                client.SortCaculationAsync(array, numbers); 

          4.   在完成事件响应函数中获取WebService计算的结果。

    void client_SortCaculationCompleted(object sender, SortCaculationCompletedEventArgs e)
            {
                if (e.Result!= null)
                {
                    array = e.Result;
                    MaxValuetextBlock.Text  = e.Result[e.Result.Count-1].ToString();
                    for (int i = 0; i < array.Count; i++)
                    {
                        SorttextBlock.Text += e.Result[i] + " ";
                    }
                }
               
            }
    
            void client_AddCaculationCompleted(object sender, AddCaculationCompletedEventArgs e)
            {
                AddResulttextBlock.Text = e.Result.ToString();
            }

    以上工作便是调用WebService的基本步骤。

    下面来看一看最后完整的代码:

    这里声明了一个Random变量,用户生成随机数组,然后调用Fortran的DLL,对随机数组排序。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using SilverlightApplication.CaculationService;
    namespace SilverlightApplication
    {
        public partial class MainPage : UserControl
        {
            ArrayOfDouble array = new ArrayOfDouble();
            CaculationService.CaculationWebServiceSoapClient client = new CaculationWebServiceSoapClient();
            public MainPage()
            {
                InitializeComponent();
                client.AddCaculationCompleted += new EventHandler<AddCaculationCompletedEventArgs>(client_AddCaculationCompleted);
                client.SortCaculationCompleted += new EventHandler<SortCaculationCompletedEventArgs>(client_SortCaculationCompleted);
                CaculationButton.Click += new RoutedEventHandler(CaculationButton_Click);
            }
    
            void CaculationButton_Click(object sender, RoutedEventArgs e)
            {
                Random rnd = new Random();
                int numbers = rnd.Next(8, 12);
    
                for (int i = 0; i < numbers; i++)
                {
                    double temp;
                    temp = rnd.Next(100);
                    RandomtextBlock.Text += temp + " ";
                    array.Add(temp);
                }
              
                client.AddCaculationAsync(Convert.ToDouble(textBoxA.Text),Convert.ToDouble(textBoxB.Text));
                client.SortCaculationAsync(array, numbers);
            }
    
            void client_SortCaculationCompleted(object sender, SortCaculationCompletedEventArgs e)
            {
                if (e.Result!= null)
                {
                    array = e.Result;
                    MaxValuetextBlock.Text  = e.Result[e.Result.Count-1].ToString();
                    for (int i = 0; i < array.Count; i++)
                    {
                        SorttextBlock.Text += e.Result[i] + " ";
                    }
                }
               
            }
    
            void client_AddCaculationCompleted(object sender, AddCaculationCompletedEventArgs e)
            {
                AddResulttextBlock.Text = e.Result.ToString();
            }
        }
    }

    随后的运行效果:

     (版权所有,转载请标明出处)

  • 相关阅读:
    【转载】远程桌面协议浅析(VNC/SPICE/RDP)
    【yumex图形安装双击】【转载】CentOS yum的详细使用方法
    【转载】复制文件到已存在的Jar
    黑马程序猿——19,Collections工具类,Arrays工具类,高级for循环,可变參数,静态导入
    在UIView中加入应用下载信息模块
    TCP/IP 寻址
    软考征程之Pv操作
    4:2:0 Video Pixel Formats
    hdu 4908 Task schedule 须要预处理
    sql serve 跨server查询数据方法
  • 原文地址:https://www.cnblogs.com/potential/p/2762306.html
Copyright © 2011-2022 走看看