用 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();
        }
    }
}

隨后的運行效果:

 (版權所有,轉載請標明出處)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM