{"id":6773,"date":"2014-12-20T14:21:18","date_gmt":"2014-12-20T05:21:18","guid":{"rendered":"http:\/\/www.moonmile.net\/blog\/?p=6773"},"modified":"2014-12-21T00:44:10","modified_gmt":"2014-12-20T15:44:10","slug":"lets-call-all-fortran-dll-from-f-language","status":"publish","type":"post","link":"http:\/\/www.moonmile.net\/blog\/archives\/6773","title":{"rendered":"Let&#8217;s call Fortran DLL from F# language."},"content":{"rendered":"<p>This text is 14th article in F# Advent Calendar 2014 in Japanese.<\/p>\n<p>The original article&#8217;s the Japanese, but since there was a request, I am rewriting in English. So this year is also in English version, and users to access the F# Advent of English version and traced from the following.<\/p>\n<p>F# Advent Calendar 2014 &#8211; connpass<br \/>\n<a href=\"http:\/\/connpass.com\/event\/9758\/\">http:\/\/connpass.com\/event\/9758\/<\/a><br \/>\nF# Advent Calendar in English 2014 | Sergey Tihon&#8217;s Blog<br \/>\n<a href=\"http:\/\/sergeytihon.wordpress.com\/2014\/11\/24\/f-advent-calendar-in-english-2014\/\">http:\/\/sergeytihon.wordpress.com\/2014\/11\/24\/f-advent-calendar-in-english-2014\/<\/a><\/p>\n<p>Well, last year it wrote of that &#8220;before the F# and Fortran story &#8230; of&#8221; What it is sadly the setback was me&#8230;, this time agein !!! We succeeded in calling a Fortran from F#, who deals and technical information for you, but the time being, because the head is harf-joke article capital F connection :P<\/p>\n<h2>Make DLL by Fortarn<\/h2>\n<p>This DLL is made by Intel Visual Fortran 2013.<\/p>\n<p><a href=\"http:\/\/www.moonmile.net\/blog\/wp-content\/uploads\/2014\/12\/wpid-dworkblogimage20141214_01org.jpg\"><img decoding=\"async\" src=\"http:\/\/www.moonmile.net\/blog\/wp-content\/uploads\/2014\/12\/wpid-dworkblogimage20141214_01thum.jpg\" border=\"0\" \/><\/a><\/p>\n<p>Intel Fortan can make DLL on Windows. Export Function is defined &#8220;!DEC$ ATTRIBUTES DLLEXPORT::&lt;EXPORT-FUNCTION&gt;&#8221;. We have a fortran fo GNU, but without that it was made only static libraries more of over there, I do not know well. However, it is possible to to create a *.so file. If you are run on linux use as it is from the C language, you&#8217;ll probably make in a manner similar from F#.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n! This function has two number parameters.\r\ninteger function add1( a, b )\r\n    !DEC$ ATTRIBUTES DLLEXPORT::ADD1\r\n    integer, intent(in) :: a, b\r\n    integer :: total\r\n\r\n    total = a + b\r\n    add1  = total\r\nend function add1\r\n\r\n! This function has a One-dimensional array parameter.\r\ninteger function sum1( v, count )\r\n    !DEC$ ATTRIBUTES DLLEXPORT::SUM1\r\n    integer, intent(in) :: v(10)\r\n    integer, intent(in) :: count\r\n    integer :: i, total\r\n\r\n    total = 0\r\n    do i=1,count\r\n        print *, 'in sum1: ', i, v(i)\r\n        total = total + v(i)\r\n    end do\r\n    sum1 = total\r\n    end function sum1\r\n\r\n! This function has a Two-dimensional array parameter.\r\ninteger function sum2( v, cnti, cntj )\r\n    !DEC$ ATTRIBUTES DLLEXPORT::SUM2\r\n    integer :: v(3,4)\r\n    integer :: cnti, cntj\r\n    integer :: i,j\r\n    integer :: total\r\n\r\n    total = 0\r\n    do j=1,cntj\r\n        do i=1,cnti\r\n            print *,i,j,v(i,j)\r\n            total = total + v(i,j)\r\n        end do\r\n    end do\r\n    sum2 = total\r\nend function sum2\r\n<\/pre>\n<p>Fortran of contents is too cheap, but I have tried an array numeric (int type). To after practice, We should try double, the per float.<\/p>\n<h2>Try to call from C++ Language<\/h2>\n<p>Let&#8217;s call from C++ in order to confirm the operation. The DLL function that is published from Fortran, and I call using the dllimport, but I just want to note is where we pass the value is in the pointer. because via global variables rather than via this Fortran function of passing stack. In the case of C language and pass laden with value on the stack (C# same when passing from a .NET language, etc.), when it passed to Fortran, that do not attention to this, it&#8217;s a strange feeling. Well, when you&#8217;re doing just Fortran, and so convenient to be very well done to be taken into account (like pass as it is a huge array).<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n#include &amp;quot;stdafx.h&amp;quot;\r\n#include &lt;iostream&gt;\r\n\r\n#define DllImport __declspec( dllimport )\r\n\r\nextern &amp;quot;C&amp;quot; {\r\n\tDllImport int ADD1(const int *, const int *);\r\n\tDllImport int SUM1( int(*)&#x5B;] , const int *);\r\n\tDllImport int SUM2(int(*)&#x5B;4]&#x5B;3], const int *, const int *);\r\n}\r\n\r\nint _tmain(int argc, _TCHAR* argv &#x5B;])\r\n{\r\n\tint x = 10;\r\n\tint y = 20;\r\n\tint ans = ADD1(&amp;x, &amp;y);\r\n\tstd::cout &lt;&lt; &amp;quot;ans &amp;quot; &lt;&lt; ans &lt;&lt; std::endl;\r\n\r\n\tint  v&#x5B;] = { 1, 2, 3, 4, 5 };\r\n\tint cnt = 5;\r\n\tint ans2 = SUM1((int(*)&#x5B;])&amp;v, &amp;cnt);\r\n\tstd::cout &lt;&lt; &amp;quot;ans2 &amp;quot; &lt;&lt; ans2 &lt;&lt; std::endl;\r\n\r\n\tint v2&#x5B;]&#x5B;3] = {\r\n\t\t{1,2,3},\r\n\t\t{11,22,33},\r\n\t\t{10,20,30},\r\n\t\t{100,200,300}\r\n\t};\r\n\tint cnti = 3;\r\n\tint cntj = 4;\r\n\tint ans3 = SUM2( &amp;v2, &amp;cnti, &amp;cntj);\r\n\tstd::cout &lt;&lt; &amp;quot;ans3 &amp;quot; &lt;&lt; ans3 &lt;&lt; std::endl;\r\n\r\n\treturn 0;\r\n}\r\n<\/pre>\n<p>If we run this code, you will like that.<\/p>\n<p><a href=\"http:\/\/www.moonmile.net\/blog\/wp-content\/uploads\/2014\/12\/wpid-dworkblogimage20141214_02org.jpg\"><img decoding=\"async\" src=\"http:\/\/www.moonmile.net\/blog\/wp-content\/uploads\/2014\/12\/wpid-dworkblogimage20141214_02thum.jpg\" border=\"0\" \/><\/a><\/p>\n<h2>Try to Call from C# Language<\/h2>\n<p>Let&#8217;s rewrite in C#. And to use the DllImport is we ware found, but it does not do not pass a pointer int type, we can use the &#8216;ref&#8217; keyword. Call form of the function, we need to be defined explicitly &#8220;CallingConvention = CallingConvention.Cdecl&#8221;.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nclass Program\r\n{\r\n\t&#x5B;DllImport(&quot;FModule.dll&quot;, CallingConvention = CallingConvention.Cdecl)]\r\n\textern static int SUM1(&#x5B;In] int&#x5B;] v, &#x5B;In] ref int count);\r\n\t&#x5B;DllImport(&quot;FModule.dll&quot;, CallingConvention = CallingConvention.Cdecl)]\r\n\textern static int SUM2(&#x5B;In] int&#x5B;,] v, &#x5B;In] ref int cnti, &#x5B;In] ref int cntj);\r\n\t&#x5B;DllImport(&quot;FModule.dll&quot;, CallingConvention = CallingConvention.Cdecl)]\r\n\textern static int ADD1(&#x5B;In] ref int a, &#x5B;In] ref int b);\r\n\r\n\tstatic void Main(string&#x5B;] args)\r\n\t{\r\n\t\tint a = 10;\r\n\t\tint b = 20;\r\n\t\tint ans = ADD1(ref a, ref b);\r\n\t\tConsole.WriteLine(&quot;ans {0}&quot;, ans);\r\n\r\n\t\tint&#x5B;] v = { 1, 2, 3, 4, 5 };\r\n\t\tint cnt = v.Length;\r\n\t\tint ans2 = SUM1(v, ref cnt);\r\n\t\tConsole.WriteLine(&quot;ans2 {0}&quot;, ans2);\r\n\t\t\/*\r\n\t\tint&#x5B;]&#x5B;] v2 = {\r\n\t\t\t\t\t\t\tnew int&#x5B;]{1,2,3,4},\r\n\t\t\t\t\t\t\tnew int&#x5B;]{11,22,33,44},\r\n\t\t\t\t\t\t\tnew int&#x5B;]{10,20,30,40},\r\n\t\t\t\t\t\t};\r\n\t\t*\/\r\n\t\tint&#x5B;,] v2 = {\r\n\t\t\t\t\t\t{1,2,3},\r\n\t\t\t\t\t\t{11,22,33},\r\n\t\t\t\t\t\t{10,20,30},\r\n\t\t\t\t\t\t{100,200,300},\r\n\t\t\t\t\t};\r\n\t\tint cnti = 3;\r\n\t\tint cntj = 4;\r\n\t\tint ans3 = SUM2(v2, ref cnti, ref cntj);\r\n\t\tConsole.WriteLine(&quot;ans3 {0}&quot;, ans3);\r\n\t}\r\n<\/pre>\n<p>When you pass a two-dimensional array, int[][] in rather than int[,] you can use the C++ and because the int value the same as in the contiguous memory and Fortran is to be placed. When we call the ADD1 function is cumbersome put the ref to, but you can call this correctly the DLL of Fortran.<\/p>\n<h2>Try to call from F# !!!<\/h2>\n<p>Let&#8217;s rewrite more F#. This pointer which is export from dll is int&amp; we declare as.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nopen System\r\nopen System.Runtime.InteropServices\r\n\r\ntype ARY2D = int&#x5B;,]\r\n\r\n&#x5B;&lt;AutoOpen&gt;]\r\nmodule FDLL =\r\n  &#x5B;&lt;DllImport(&amp;quot;FModule.dll&amp;quot;, CallingConvention = CallingConvention.Cdecl)&gt;]\r\n  extern int ADD1(int&amp; a, int&amp; b)\r\n  &#x5B;&lt;DllImport(&amp;quot;FModule.dll&amp;quot;, CallingConvention = CallingConvention.Cdecl)&gt;]\r\n  extern int SUM1(int&#x5B;] v, int&amp; count )\r\n  \/\/ cannot use int&#x5B;,], so we defined &#039;ARY2D&#039; alias class.\r\n  &#x5B;&lt;DllImport(&amp;quot;FModule.dll&amp;quot;, CallingConvention = CallingConvention.Cdecl)&gt;]\r\n  \/\/ extern int SUM2(int&#x5B;,] v, int&amp; cnti, int&amp; cnt2 )\r\n  extern int SUM2(ARY2D v, int&amp; cnti, int&amp; cnt2 )\r\n\r\nlet mutable a = 10\r\nlet mutable b = 20\r\nlet ans = ADD1( &amp;a , &amp;b )\r\n\r\nConsole.WriteLine( &amp;quot;ans {0}&amp;quot;, ans )\r\n\r\nlet mutable v = &#x5B;|1;2;3;4;5|]\r\nlet mutable cnt = v.Length\r\nlet ans2 = SUM1( v, &amp;cnt )\r\n\r\nConsole.WriteLine( &amp;quot;ans2 {0}&amp;quot;, ans2 )\r\n\r\n\/\/ two-dimensional array is made by Array2D module.\r\nlet vv = &#x5B;|\r\n    &#x5B;|1;2;3|];\r\n    &#x5B;|11;22;33|];\r\n    &#x5B;|10;20;30|];\r\n    &#x5B;|100;200;300|];\r\n  |]\r\nlet v2 = Array2D.init 4 3 ( fun i j -&gt; vv.&#x5B;i].&#x5B;j])\r\n\r\nlet mutable cnti = 3\r\nlet mutable cntj = 4\r\nlet ans3 = SUM2( v2, &amp;cnti, &amp;cntj )\r\n\r\nConsole.WriteLine( &amp;quot;ans3 {0}&amp;quot;, ans3 )\r\n<\/pre>\n<p>C# is not enough &#8230; write simpler compared with F#, I do not change much. Than that, it&#8217;s worrisome is is where you must use let &#8216;mutable&#8217; is to want to pass by const. This is a limitation of Fortran call, in order to pass a pointer value, the variable of a even if it is not changed content is not pass and do not &#8216;mutable&#8217;. Here is where I want to twist. Though it pains of immutable values, it is a place me.<\/p>\n<p>C# 2-dimensional array in int [,] since the was an unclear writing is how I in F # &#8230; but, how was I understand. With Array2D int [,] you can make a considerable thing. This, what another twist necessary int when you extern [,] it can not be the type specified in, we will create the alias. Here, extern int SUM2 by creating a type alias that ARY2D and is doing. In this way, you will be passed as the same as a two-dimensional array with C++.<\/p>\n<p><a href=\"http:\/\/www.moonmile.net\/blog\/wp-content\/uploads\/2014\/12\/wpid-dworkblogimage20141214_03org.jpg\"><img decoding=\"async\" src=\"http:\/\/www.moonmile.net\/blog\/wp-content\/uploads\/2014\/12\/wpid-dworkblogimage20141214_03thum.jpg\" border=\"0\" \/><\/a><\/p>\n<p>Oh, Order of two-dimensional array will not unlike those of C++, but this is that the charm ;)<\/p>\n<h2>At the end<\/h2>\n<p>That is why, one New Year&#8217;s Eve of projects? As, was able story article dealing with the Fortran from F#. This, or the existing Fortran library can make an app that was made from F#, Who&#8217;s the obtained technical information but, Well, it is possible to that wanted to do. Everyone, a good Christmas !!!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This text is 14th article in F# Advent Calendar 2014 in Japanese. The original article&#8217;s the Japanese, b &hellip; <a href=\"http:\/\/www.moonmile.net\/blog\/archives\/6773\">\u7d9a\u304d\u3092\u8aad\u3080 <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[3],"tags":[],"class_list":["post-6773","post","type-post","status-publish","format-standard","hentry","category-dev"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"http:\/\/www.moonmile.net\/blog\/wp-json\/wp\/v2\/posts\/6773","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.moonmile.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.moonmile.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.moonmile.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/www.moonmile.net\/blog\/wp-json\/wp\/v2\/comments?post=6773"}],"version-history":[{"count":2,"href":"http:\/\/www.moonmile.net\/blog\/wp-json\/wp\/v2\/posts\/6773\/revisions"}],"predecessor-version":[{"id":6775,"href":"http:\/\/www.moonmile.net\/blog\/wp-json\/wp\/v2\/posts\/6773\/revisions\/6775"}],"wp:attachment":[{"href":"http:\/\/www.moonmile.net\/blog\/wp-json\/wp\/v2\/media?parent=6773"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.moonmile.net\/blog\/wp-json\/wp\/v2\/categories?post=6773"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.moonmile.net\/blog\/wp-json\/wp\/v2\/tags?post=6773"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}