回 帖 发 新 帖 刷新版面

主题:[原创]C#同FORTRAN混合编程的字符串传递方法

[u][b]C#与FORTRAN混合编程中的字符串传递方法[/b][/u]

[b]Introduction:[/b]
  前段时间编程的时候遇到的问题,也曾经发过帖子但是没有能够得到解决.后来有网友通过邮件联系希望能够找到解决字符串传递的方法,并且提供了相关的资料.笔者自己也通过一些文献的查找,最后调试出了一种能够进行传递的方法.

[b]Method Principle:[/b]
今晚看了几篇文献发现了有一种方法可以将字符串传递过去
而且我也编程试过,可以运行

原理很简单,就是避免直接的进行不同类型的字符串传递
换用数组传递,具体操作流程如下:
C#中的字符串传向FORTRAN
step1: 在C#中将字符串分割为字符数组
step2: 再将字符数组转为ASCII码数组,然后传递给FORTRAN
step3: 在FORTRAN中利用CHAR()函数将ASCII码还原为字符串即可
NOTE: FORTRAN传向C#也是可以采用相同的思路进行

[b]Applied Example[/b]
Example Codes:
---------------------------------------------------------------------
//C#中的字符串分割,并转存为ASCII码数组
            string c = "abcdefg";          
            ASCIIEncoding ascii = new ASCIIEncoding();
            int[] num = new int[c.Length];
            for (int i = 0; i < c.Length; i++)
            {
                num[i] = (int)ascii.GetBytes(c)[i];
               
            }
            
            int m = c.Length;
            [color=FF0000]S(ref num[0],ref m);[/color]
---------------------------------------------------------------------
//C#调用DLL声明及操作
[DllImport("DLL TEST.dll", SetLastError = true, CharSet = CharSet.Unicode, 
                           CallingConvention = CallingConvention.StdCall)]
public static extern void S(ref int ka, ref int m);

//参数说明: ka为ASCII码数组名; m为ka数组大小(即字符串长度)
----------------------------------------------------------------------
!FORTRAN中还原操作
subroutine s(ka,m)
 !dec$ attributes dllexport ::s
 character(m)::str
 dimension ka(m)
 integer i
 integer x,y
 do i=1,m
   str(i:i)=char(ka(i))
 enddo 
end
-----------------------------------------------------------------------

[b]Conclution and Discussion[/b]
  字符串的传递是混合编程中需要考虑得最多的问题,因此如何进行有效的数据传递是关键点.我们提出的方法能够成功的进行字符串传递.结合实际编程的需要,可以进行例如文件名,文件路径的传递,利用FORTRAN方便的文件读写功能等应用.
  
  关于字符串的传递还可以有其它的解决办法,例如针对FORTRAN中的ASC类型和C#中Unicode类型以及各自的特点可以进行转换;
  混合编程的优势是很明显的,解决好基本的传递问题以后,可以更大限度的发挥面向对象和面向过程的结合;底层科学计算语言与高层界面开发的结合的完美展现!

[b]Acknowledgements[/b]
  感谢网友:
***********************************
 Zhoutao, M.En.                
 School of Civil Engneering CSU 
 No.22 Shaoshan SouthRoad       
 Changsha, P.R.China             
 Zip Code: 410075            
 Tel:       86-731-2655003     
 CellPhone: 13975809495       
***********************************

[b]Technique Support[/b]
  欢迎交流讨论
Email: mou_yq@126.com

回复列表 (共5个回复)

沙发

搂主上面的方法很好很通用!将字符串在各自的领域里转换成相应的数值在做参数传输可以节省很多因参数类型不同带来的麻烦。好贴一定要顶:)

板凳

下面是我根据Compaq Visual Fortran Version 6.6 随机帮助文件中的Programmer's Guide->Creating Fortran DLLs &->Programming with Mixed Languages 和Language Reference->A to Z Reference->A to B->ATTRIBUTES 等相关部分的内容做出的一个测试例程,用来说明C#调用Fortran DLL过程中参数传入Fortran的实现(只涉及到了数值类型和字符及字符串类型,其它类型读者可以继续到帮助中阅读相关资料)。

!FortranDLL.f90文件的内容如下:
!用来建立DLL项目
!函数WTSTR(Str)用来建立Str文件并在该文件里记录Str字符串的内容
Subroutine writestr(str)
!DEC$ ATTRIBUTES DLLEXPORT,ALIAS:'WTSTR':: Writestr
Character*(*) str
Open(1,file=str)
Write(1,*) str  
End subroutine writestr
!
!函数Iadd2(A,B)用来就算两个整型数A、B的和并将结果输出到屏幕
Subroutine iadd2(a,b)
  !DEC$ ATTRIBUTES C, DLLEXPORT,ALIAS:'Iadd2'::Iadd2
  integer::a,b
  integer::sum
  sum=a+b
  write(*,*)"The sum:",sum,"in DLL iadd2"
End subroutine iadd2
!上述Iadd2函数中用来C属性字段,是用来说明参数是按值来传送的,而在WTSTR函数中因为是
!用来传递字符类型的,所以不能用“C”。(If C or STDCALL is specified for a subprogram, 
!arguments (except for arrays and characters) are passed by value. )


//C#中的调用代码如下:
//这部分代码将编译生成.EXE可执行程序,调用上面的DLL
using System;
using System.Runtime.InteropServices;
namespace CCallDll
{
    class Program
    {
        [DllImport("dlltest.dll")] //WTSTR函数说明部分,注意此处字符串参数的传递
        public static extern void WTSTR(String str, int strlength);
        [DllImport("dlltest.dll")] //Iadd2函数说明部分
                                   //两种类型的参数传递涉及到在Fortran程序中的处理也不一样
        public static extern void Iadd2(int a, int b);
        //主程序入口
        static void Main(string[] args)
        {
            //Delcare the String Variable. Notice:it's Unicode 
            String unicodeString = "This.txt";
            Console.WriteLine("Original string is      : {0}", unicodeString );
            Console.WriteLine("The length of the string: {0}",  unicodeString .Length);
            //Call the Function of WTSTR( ,) 此处增加了一个表示字符串长度的参数是因为
            //Fortran、和C#存贮字符串的方法不一样(详情查阅相关资料,有很多介绍)
            WTSTR(unicodeString, unicodeString.Length ); 
            Iadd2(1000, 10);
        }
    }
}

上述例程经过笔者自己测试,运行良好:) 
测试环境:Microsoft Visual Studio 2005
          Intel Visual Fortran 9.1
          Windows XP / Windows Vista


我也感谢一下楼上的网友——杨清 吧:)




3 楼

没有用Fortran 2003里的标准函数,那么以上做法就是编译器相关的。

4 楼

sjohn:

请问你是用的 FORTRAN 2003吗?
已经有安装程序了吗? 

5 楼

太TM感谢你了,我用这个程序按部就班的解决了数组传递问题,别人写的都不如你清楚。

我来回复

您尚未登录,请登录后再回复。点此登录或注册